diff --git a/.gitattributes b/.gitattributes index e3fa62677708f0dce0d86c373df1b7919158aad1..3003752d3fbb1515990e9bf043f218938091b15f 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1613,6 +1613,7 @@ CEP/Pipeline/recipes/sip/nodes/setupparmdb.py eol=lf CEP/Pipeline/recipes/sip/nodes/setupsourcedb.py eol=lf CEP/Pipeline/recipes/sip/nodes/vdsmaker.py eol=lf CEP/Pipeline/recipes/sip/pipeline.cfg.in eol=lf +CEP/Pipeline/recipes/sip/pipeline.cfg.thead01.cep4 -text CEP/Pipeline/recipes/sip/plugins/PipelineStep_addMapfile.py -text CEP/Pipeline/recipes/sip/plugins/PipelineStep_changeMapfile.py -text CEP/Pipeline/recipes/sip/plugins/PipelineStep_combineParsets.py -text @@ -2344,6 +2345,13 @@ CMake/variants/variants.node503 -text CMake/variants/variants.node521 -text CMake/variants/variants.phi -text CMake/variants/variants.sharkbay -text +Docker/docker-build-all.sh -text +Docker/lofar-base/Dockerfile.tmpl -text +Docker/lofar-base/bashrc -text +Docker/lofar-base/chuser.sh -text +Docker/lofar-base/subversion_servers -text +Docker/lofar-outputproc/Dockerfile.tmpl -text +Docker/lofar-pipeline/Dockerfile.tmpl -text JAVA/GUI/Plotter/dist/lib/sgt.jar -text svneol=unset#unset JAVA/GUI/Plotter/doc/Plotter.EAP -text JAVA/GUI/Plotter/doc/javadoc/resources/inherit.gif -text diff --git a/CEP/Pipeline/framework/lofarpipe/support/remotecommand.py b/CEP/Pipeline/framework/lofarpipe/support/remotecommand.py index 9bb498e5514559e110c153312b27aaef97677843..82950986177ebb0cf1e16735b99f0861fa2f5ad0 100644 --- a/CEP/Pipeline/framework/lofarpipe/support/remotecommand.py +++ b/CEP/Pipeline/framework/lofarpipe/support/remotecommand.py @@ -78,6 +78,8 @@ def run_remote_command(config, logger, host, command, env, arguments = None): except: method = None + logger.info("********************** Remote method is %s" % method) + if method == "paramiko": try: key_filename = config.get('remote', 'key_filename') @@ -94,13 +96,17 @@ def run_remote_command(config, logger, host, command, env, arguments = None): return run_via_mpiexec_cep(logger, command, arguments, host) elif method == "slurm_srun_cep3": return run_via_slurm_srun_cep3(logger, command, arguments, host) + elif method == "custom_cmdline": + return run_via_custom_cmdline(logger, host, command, env, arguments, config) else: return run_via_ssh(logger, host, command, env, arguments) def run_via_slurm_srun_cep3(logger, command, arguments, host): + logger.debug("Dispatching command to %s with srun" % host) for arg in arguments: command = command + " " + str(arg) commandstring = ["srun","-N 1","-n 1","-w",host, "/bin/sh", "-c", "hostname && " + command] + #commandstring = ["srun","-N 1","--cpu_bind=map_cpu:none","-w",host, "/bin/sh", "-c", "hostname && " + command] # we have a bug that crashes jobs when too many get startet at the same time # temporary NOT 100% reliable workaround #from random import randint @@ -179,6 +185,53 @@ def run_via_ssh(logger, host, command, environment, arguments): process.kill = lambda : os.kill(process.pid, signal.SIGKILL) return process +def run_via_custom_cmdline(logger, host, command, environment, arguments, config): + """ + Dispatch a remote command via a customisable command line + + We return a Popen object pointing at the running executable, to which we add a + kill method for shutting down the connection if required. + + The command line is taken from the "remote.cmdline" configuration option, + with the following strings replaced: + + {host} := host to execute command on + {command} := bash command line to be executed + {uid} := uid of the calling user + + {image} := docker.image configuration option + {slurm_job_id} := the SLURM job id to allocate resources in + + """ + commandArray = ["%s=%s" % (key, value) for key, value in environment.items()] + commandArray.append(command) + commandArray.extend(re.escape(str(arg)) for arg in arguments) + commandStr = " ".join(commandArray) + + try: + image = config.get('docker', 'image') + except: + image = "lofar" + + # Construct the full command line, except for {command}, as that itself + # can contain spaces which we don't want to split on. + full_command_line = config.get('remote', 'cmdline').format( + uid = os.geteuid(), + slurm_job_id = os.environ.get("SLURM_JOB_ID"), + docker_image = image, + host = host, + command = "{command}" + ).split(' ') + + # Fill in {command} somewhere + full_command_line = [x.format(command = commandStr) for x in full_command_line] + + logger.debug("Dispatching command to %s with custom_cmdline: %s" % (host, full_command_line)) + + process = spawn_process(full_command_line, logger) + process.kill = lambda : os.kill(process.pid, signal.SIGKILL) + return process + def run_via_paramiko(logger, host, command, environment, arguments, key_filename): """ Dispatch a remote command via paramiko. @@ -270,8 +323,7 @@ class ComputeJob(object): "PYTHONPATH": os.environ.get('PYTHONPATH'), "LD_LIBRARY_PATH": os.environ.get('LD_LIBRARY_PATH'), "LOFARROOT" : os.environ.get('LOFARROOT'), - "QUEUE_PREFIX" : os.environ.get('QUEUE_PREFIX',''), - "LOFAR_OBSID" : os.environ.get('LOFAR_OBSID','') + "QUEUE_PREFIX" : os.environ.get('QUEUE_PREFIX','') }, arguments = [id, jobhost, jobport] ) diff --git a/CEP/Pipeline/recipes/sip/pipeline.cfg.thead01.cep4 b/CEP/Pipeline/recipes/sip/pipeline.cfg.thead01.cep4 new file mode 100644 index 0000000000000000000000000000000000000000..62ad298207d88a02f6ed3c1c416a505127967774 --- /dev/null +++ b/CEP/Pipeline/recipes/sip/pipeline.cfg.thead01.cep4 @@ -0,0 +1,89 @@ +# This pipeline.cfg was used on the CEP4 test system to show how Docker and SLURM +# can be used to distribute and run jobs. +# +# Is called as follows (inside a SLURM job allocation, f.e. "salloc -N 2"). Replace directory names +# where needed: +# +# # Create this on every node +# CONFIGDIR=/globalhome/mol/regression_test +# HOSTS=(`scontrol show hostnames $SLURM_JOB_NODELIST`) +# +# # $CONFIGDIR is local, and ocntains both the working_dir (for input/output data) and the config files +# # /share is a shared disk for the vds files, map files, logs. +# +# docker run --rm -e SLURM_JOB_ID=${SLURM_JOB_ID} -e LUSER=${UID} -v $HOME/.ssh:/home/lofar/.ssh:ro -v $CONFIGDIR:$CONFIGDIR -v /shared:/shared --net=host lofar-patched /bin/bash -c "\"$EXTRA_CMDS;python $CONFIGDIR/regression_test_runner.py preprocessing_pipeline --pipelinecfg $CONFIGDIR/pipeline.cfg --testdata $CONFIGDIR/data --computehost1 ${HOSTS[0]} --computehost2 ${HOSTS[1]} --workdir $CONFIGDIR/working_dir --rundir $CONFIGDIR/rundir\"" + + +[DEFAULT] +lofarroot = /opt/lofar +casaroot = /opt/casacore +pyraproot = /opt/python-casacore/pyrap +hdf5root = +wcsroot = /opt/wcslib +pythonpath = /opt/lofar/lib/python2.7/site-packages +# runtime dir is a global FS (nfs, lustre) to exchange small files (parsets, vds, map files, etc) +runtime_directory = /shared/mol/regression_test/rundir +recipe_directories = [%(pythonpath)s/lofarpipe/recipes] +# working dir is the local dir in which input/output dataproducts reside +working_directory = /globalhome/mol/regression_test/working_dir +task_files = [%(lofarroot)s/share/pipeline/tasks.cfg] + +[layout] +job_directory = %(runtime_directory)s/%(job_name)s + +[cluster] +clusterdesc = %(lofarroot)s/share/local.clusterdesc + +[deploy] +engine_ppath = %(pythonpath)s:%(pyraproot)s/lib:/opt/cep/pythonlibs/lib/python/site-packages +engine_lpath = %(lofarroot)s/lib:%(casaroot)s/lib:%(pyraproot)s/lib:%(hdf5root)s/lib:%(wcsroot)s/lib + +[logging] +log_file = %(runtime_directory)s/%(job_name)s/logs/%(start_time)s/pipeline.log +xml_stat_file = %(runtime_directory)s/%(job_name)s/logs/%(start_time)s/statistics.xml + +[feedback] +# Method of providing feedback to LOFAR. +# Valid options: +# messagebus Send feedback and status using LCS/MessageBus +# none Do NOT send feedback and status +method = none + +[docker] +image = lofar-patched + +[remote] +#method = slurm_srun_cep3 +#method = ssh_docker +method = custom_cmdline +max_per_node = 1 + +# We take the following path to start a remote container: +# +# [container] --SSH--> [host] --SRUN--> [worker node] --DOCKER--> [container] +# +# This path is needed because running SRUN from within the container needs a lot of cluster-specific infra +# (SLURM config files, Munge keys, correct Munge user ID, munged). +# +# Throughout this path, we maintain: +# * userid, which is set to the user that started the master script container (-e LUSER=`id -u`) +# * environment (sudo -p, docker -e K=V, etc) +# * pseudo-tty to prevent buffering logs (ssh -tt, docker -t) + +# +# host -> worker node: srun -w {host} -N 1 -n 1 --jobid={slurm_job_id} +# Needs the specific host, because the test system does not have a global file system. +# +# worker node -> container: docker run -t --rm -e LUSER={uid} -w g -v /home/mol/.ssh:/home/lofar/.ssh:ro -v /globalhome/mol/regression_test:/globalhome/mol/regression_test -v /shared:/shared --net=host {docker_image} +# Starts the container on the worker node, with pretty much the same parameters as the master container: +# +# --rm: don't linger resources when the container exits +# -e LUSER=(uid): set the user to run as (the calling user) +# -h {host}: set container hostname (for easier debugging) (doesnt work yet, using --net=host instead) +# -v: map the directories for input/output data, shared storage (parsets, vds files, etc) +# +# /bin/bash -c +# +# Required because the pipeline framework needs some bash functionality in the commands it starts. +#cmdline = ssh -n -tt -x localhost srun -w {host} -N 1 -n 1 --jobid={slurm_job_id} docker run -t --rm -e LUSER={uid} -w g -v /home/mol/.ssh:/home/lofar/.ssh:ro -v /globalhome/mol/regression_test:/globalhome/mol/regression_test -v /shared:/shared --net=host {docker_image} /bin/bash -c +cmdline = ssh -n -tt -x localhost srun -w {host} -N 1 -n 1 --jobid={slurm_job_id} docker run -t --rm -e LUSER={uid} -v %(runtime_directory)s:%(runtime_directory)s -v %(working_directory)s:%(working_directory)s --net=host {docker_image} /bin/bash -c "\"{command}\"" diff --git a/CMake/LofarPackageList.cmake b/CMake/LofarPackageList.cmake index c1990c2763c8a3e6ce317952a67fff78c7aae35d..1e8ed2516bee6c38dc4c7c2eb12901c084f97c5a 100644 --- a/CMake/LofarPackageList.cmake +++ b/CMake/LofarPackageList.cmake @@ -16,6 +16,7 @@ if(NOT DEFINED LOFAR_PACKAGE_LIST_INCLUDED) set(LOFAR_PACKAGE_LIST_INCLUDED TRUE) set(Calibration_SOURCE_DIR ${CMAKE_SOURCE_DIR}/CEP/Calibration) set(DP3_SOURCE_DIR ${CMAKE_SOURCE_DIR}/CEP/DP3) + set(Docker_SOURCE_DIR ${CMAKE_SOURCE_DIR}/Docker) set(GSM_SOURCE_DIR ${CMAKE_SOURCE_DIR}/CEP/GSM) set(Imager_SOURCE_DIR ${CMAKE_SOURCE_DIR}/CEP/Imager) set(LMWCommon_SOURCE_DIR ${CMAKE_SOURCE_DIR}/CEP/LMWCommon) diff --git a/CMake/UpdatePackageVersion.cmake.in b/CMake/UpdatePackageVersion.cmake.in index 6732c27242cc2db0c4d64eb43aca04dc8ae306e7..84f72ac731cefeec683bb723e84d0824dae066a1 100644 --- a/CMake/UpdatePackageVersion.cmake.in +++ b/CMake/UpdatePackageVersion.cmake.in @@ -77,7 +77,11 @@ if(_result EQUAL 0) endif(_root MATCHES ".+") if(_rvers MATCHES "^/trunk/") set(_rvers "trunk") + set(_branch "trunk") elseif(_rvers MATCHES "^/tags/" OR _rvers MATCHES "^/branches/") + # branch = directory right under tags/ or branches/ + string(REGEX REPLACE "^/([^/]*/[^/]*)/.*$" "\\1" _branch "${_rvers}") + # We have a task branch (for a bug) or a release branch. # Remove all but version and replace _ in version by . string(REGEX REPLACE "^/[^/]*/([^/]*)/.*$" "\\1" _rvers "${_rvers}") @@ -121,6 +125,8 @@ file(WRITE "${_file}.tmp" " // Get the info for this package.\n" " static Version getInfo();\n" "\n" + " // Get the branch that was checked out (relative to repository root).\n" + " static std::string getBranch();\n" " // Get the version number of the package (as given in repository).\n" " static std::string getVersion();\n" " // Get the svn version number of the package according to CMakeLists.txt.\n" @@ -168,12 +174,15 @@ file(APPEND "${_file}.tmp" " Version ${_pkg}Version::getInfo()\n" " {\n" " return Version (\"@PACKAGE_NAME@\",\n" + " getBranch(),\n" " getVersion(), getConfVersion(),\n" " getRevision(), getPackageRevision(),\n" " getNrChangedFiles(),\n" " getBuildTime(), getBuildUser(), getBuildMachine());\n" " }\n" "\n" + " std::string ${_pkg}Version::getBranch()\n" + " { return \"${_branch}\"; }\n" " std::string ${_pkg}Version::getVersion()\n" " { return \"${_rvers}\"; }\n" " std::string ${_pkg}Version::getConfVersion()\n" diff --git a/CMakeLists.txt b/CMakeLists.txt index ccb788fe33c4bb7b2458a73210da07d583a68bda..ea914605bb0e6cfd80c3f8dcb4117ad3c8697aa1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,6 +18,7 @@ include(LofarGeneral) ## --------------------------------------------------------------------------- include(LofarPackage) if(NOT DEFINED BUILD_PACKAGES) + lofar_add_package(Docker) lofar_add_package(LCS) lofar_add_package(CEP) lofar_add_package(RTCP) diff --git a/Docker/CMakeLists.txt b/Docker/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..060eea1d0c446ffeb5ac0433df0432c95964c845 --- /dev/null +++ b/Docker/CMakeLists.txt @@ -0,0 +1,65 @@ +# $Id$ + +lofar_package(Docker 1.0 DEPENDS Common) + +include(LofarPackageVersion) + +# Build version info +set(docker_LIB_SRCS + Package__Version.cc +) + +lofar_add_library(docker ${docker_LIB_SRCS}) + +lofar_add_bin_program(versiondocker versiondocker.cc) + +# +# For given directories, we generate the Dockerfile +# by parsing their Dockerfile.tmpl through "docker-template". +# +# "docker-template" is a script that fills in variables with +# respect to the build info (branch name, build time, etc) +# + +# Directories with Dockerfile.tmpl to parse +set(DOCKER_TEMPLATE_DIRS + lofar-base + lofar-pipeline + lofar-outputproc) + +# Note: "docker-template" only works as long as the sources are still around, +# since it uses svn to query information from them. +lofar_add_bin_scripts(docker-template) +lofar_add_sbin_scripts(docker-build-all.sh) + +# Convert Dockerfile.tmpl -> Dockerfile in ${DOCKER_TEMPLATE_DIRS} +foreach(_dir ${DOCKER_TEMPLATE_DIRS}) + # _src -> _dst + set(_src ${CMAKE_CURRENT_SOURCE_DIR}/${_dir}/Dockerfile.tmpl) + set(_dst ${CMAKE_CURRENT_BINARY_DIR}/${_dir}_Dockerfile) + + # add generating command, and (any) target to force the generation + # when "all" is build. + add_custom_command( + OUTPUT ${_dst} + COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/docker-template < ${_src} > ${_dst} + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/docker-template ${_src} ${CMAKE_CURRENT_BINARY_DIR}/versiondocker + ) + add_custom_target(${_dir}_Dockerfile_target ALL DEPENDS ${_dst}) + + # install resulting Dockerfile + install(FILES + ${_dst} + DESTINATION share/docker/${_dir} + RENAME Dockerfile + ) +endforeach() + +# Install everything else +install(DIRECTORY + lofar-base + lofar-pipeline + lofar-outputproc + DESTINATION share/docker + USE_SOURCE_PERMISSIONS + PATTERN Dockerfile.tmpl EXCLUDE) diff --git a/Docker/docker-build-all.sh b/Docker/docker-build-all.sh new file mode 100755 index 0000000000000000000000000000000000000000..71eb409a42c9e125646f6f19af6d99e96c176c21 --- /dev/null +++ b/Docker/docker-build-all.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +TAG=`echo '${LOFAR_TAG}' | docker-template` + +function build { + IMAGE=$1 + docker build -t ${IMAGE}:${TAG} ${IMAGE} +} + +cd ${LOFARROOT}/share/docker + +build lofar-base && \ +build lofar-pipeline && \ +build lofar-outputproc + diff --git a/Docker/docker-template b/Docker/docker-template new file mode 100755 index 0000000000000000000000000000000000000000..8cac4023c1e08281bdd89b8e23629812c5b084b6 --- /dev/null +++ b/Docker/docker-template @@ -0,0 +1,61 @@ +#!/bin/bash +# +# Template engine for LOFAR +# +# Reads stdin, replaces variables, writes stdout. +# +# Variables replaced: +# ${LOFAR_BRANCH_NAME} = Name of this branch, relative to root +# ${LOFAR_BRANCH_URL} = Full subversion URL for this branch +# ${LOFAR_TAG} = Tag for a Docker image +# ${LOFAR_REVISION} = SVN revision number of this checkout (or HEAD if trunk) +# ${NOW} = now in UTC (format: 2016-01-01 10:11:12) +# ${BUILD_UID} = uid of building user (=caller) +# + +# ----- LOFAR_BRANCH_NAME = branches/LOFAR-Task1234 ----- +# ----- LOFAR_BRANCH_NAME = trunk ----- +# ----- LOFAR_BRANCH_NAME = tags/LOFAR-Release-2_15_1 ----- +# ----- LOFAR_BRANCH_NAME = UNKNOWN ----- + +# Make sure we obtain info about the project source! +#PATH=$PATH:. +VERSION_INFO=`(versiondocker || ./versiondocker) 2>/dev/null` # in cmake, executable is in . + +# Extract branch name w.r.t. repository root, e.g. branches/LOFAR-Task1234 +export LOFAR_BRANCH_NAME=`echo "$VERSION_INFO" | perl -ne 'print "$1" if /branch += +(.+)/;'` + +# ----- LOFAR_BRANCH_URL = https://svn.astron.nl/LOFAR/branches/LOFAR-Task1234 ----- +# ----- LOFAR_BRANCH_URL = https://svn.astron.nl/LOFAR/trunk ----- +# ----- LOFAR_BRANCH_URL = https://svn.astron.nl/LOFAR/tags/LOFAR-Release-2_15_1 ----- + +export LOFAR_BRANCH_URL="https://svn.astron.nl/LOFAR/${LOFAR_BRANCH_NAME}" + +# ----- LOFAR_TAG = 1234 ----- +# ----- LOFAR_TAG = trunk ----- +# ----- LOFAR_TAG = 2_15_1 ----- + +case "${LOFAR_BRANCH_NAME}" in + trunk) export LOFAR_TAG=trunk ;; + tags/*) export LOFAR_TAG=${LOFAR_BRANCH_NAME##tags/LOFAR-Release-} ;; + branches/*) export LOFAR_TAG=${LOFAR_BRANCH_NAME##branches/LOFAR*Task} ;; + *) export LOFAR_TAG=latest ;; +esac + +# ----- LOFAR_REVISION = 12345 ----- + +export LOFAR_REVISION=`echo "$VERSION_INFO" | perl -ne 'print "$1" if /overall revision += +([0-9]+)/;'` + +# ----- NOW = 2016-01-01 10:11:12 ----- + +export NOW="`date -u +'%F %T'`" + +# ----- BUILD_UID = 1001 ---- + +export BUILD_UID=`id -u` + +# ----- Process input ----- + +# Insert our knowledge when processing stdin -> stdout +envsubst '$LOFAR_BRANCH_NAME $LOFAR_BRANCH_URL $LOFAR_TAG $LOFAR_REVISION $NOW $BUILD_UID' + diff --git a/Docker/lofar-base/Dockerfile.tmpl b/Docker/lofar-base/Dockerfile.tmpl new file mode 100644 index 0000000000000000000000000000000000000000..42d5fb3913e4db10f7c6e6aa521e0c56947f1985 --- /dev/null +++ b/Docker/lofar-base/Dockerfile.tmpl @@ -0,0 +1,167 @@ +# +# base +# +FROM ubuntu:14.04 + +# +# common-environment +# +ENV USER=lofar +ENV INSTALLDIR=/opt + +# +# environment +# +ENV DEBIAN_FRONTEND=noninteractive \ + PYTHON_VERSION=2.7 + +# +# versions +# +ENV CASACORE_VERSION=2.0.3 \ + CASAREST_VERSION=1.4.1 \ + PYTHON_CASACORE_VERSION=2.0.1 \ + BOOST_VERSION=1.54 + +# +# set-uid +# +ENV UID=${BUILD_UID} + +# +# set-build-options +# +ENV J=4 + +# +# Base and runtime dependencies +# +#RUN sed -i 's/archive.ubuntu.com/osmirror.rug.nl/' /etc/apt/sources.list +RUN apt-get update && apt-get upgrade -y +RUN apt-get install -y sudo python2.7 libpython2.7 && \ + apt-get install -y libblas3 liblapacke python-numpy libcfitsio3 libwcs4 libfftw3-bin libhdf5-7 libboost-python${BOOST_VERSION}.0 + +# +# setup-account +# +RUN (getent group sudo &>/dev/null || groupadd sudo) && \ + echo "useradd -m ${USERADD_FLAGS} ${USER}" && \ + useradd -m -u ${UID} ${USER} && \ + usermod -a -G sudo ${USER} && \ + echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers && \ + sed -i 's/requiretty/!requiretty/g' /etc/sudoers + +# +# setup install dir +# +RUN mkdir -p ${INSTALLDIR} && chown ${USER}.${USER} ${INSTALLDIR} + +USER ${USER} + +# +# ******************* +# Casacore +# ******************* +# +RUN sudo apt-get install -y wget git cmake g++ gfortran flex bison libblas-dev liblapacke-dev libfftw3-dev libhdf5-dev libboost-python-dev libcfitsio3-dev wcslib-dev && \ + mkdir -p ${INSTALLDIR}/casacore/build && \ + mkdir -p ${INSTALLDIR}/casacore/data && \ + cd ${INSTALLDIR}/casacore && git clone https://github.com/casacore/casacore.git src && \ + if [ "${CASACORE_VERSION}" != "latest" ]; then cd ${INSTALLDIR}/casacore/src && git checkout tags/v${CASACORE_VERSION}; fi && \ + cd ${INSTALLDIR}/casacore/data && wget --retry-connrefused ftp://ftp.astron.nl/outgoing/Measures/WSRT_Measures.ztar && \ + cd ${INSTALLDIR}/casacore/data && tar xf WSRT_Measures.ztar && rm -f WSRT_Measures.ztar && \ + cd ${INSTALLDIR}/casacore/build && cmake -DCMAKE_INSTALL_PREFIX=${INSTALLDIR}/casacore/ -DDATA_DIR=${INSTALLDIR}/casacore/data -DBUILD_PYTHON=True -DUSE_OPENMP=True -DUSE_FFTW3=TRUE ../src/ && \ + cd ${INSTALLDIR}/casacore/build && make -j ${J} && \ + cd ${INSTALLDIR}/casacore/build && make install && \ + bash -c "strip ${INSTALLDIR}/casacore/{lib,bin}/* || true" && \ + bash -c "rm -rf ${INSTALLDIR}/casacore/{build,src}" && \ + sudo apt-get purge -y wget git cmake g++ gfortran flex bison libblas-dev liblapacke-dev libfftw3-dev libhdf5-dev libboost-python-dev libcfitsio3-dev wcslib-dev && \ + sudo apt-get autoremove -y + +# +# ******************* +# Casarest +# ******************* +# +RUN sudo apt-get install -y git cmake g++ gfortran libboost-system-dev libboost-thread-dev libhdf5-dev libcfitsio3-dev wcslib-dev && \ + mkdir -p ${INSTALLDIR}/casarest/build && \ + cd ${INSTALLDIR}/casarest && git clone https://github.com/casacore/casarest.git src && \ + if [ "${CASAREST_VERSION}" != "latest" ]; then cd ${INSTALLDIR}/casarest/src && git checkout tags/v${CASAREST_VERSION}; fi && \ + cd ${INSTALLDIR}/casarest/build && cmake -DCMAKE_INSTALL_PREFIX=${INSTALLDIR}/casarest -DCASACORE_ROOT_DIR=${INSTALLDIR}/casacore ../src/ && \ + cd ${INSTALLDIR}/casarest/build && make -j ${J} && \ + cd ${INSTALLDIR}/casarest/build && make install && \ + bash -c "strip ${INSTALLDIR}/casarest/{lib,bin}/* || true" && \ + bash -c "rm -rf ${INSTALLDIR}/casarest/{build,src}" && \ + sudo apt-get purge -y git cmake g++ gfortran libboost-system-dev libboost-thread-dev libhdf5-dev libcfitsio3-dev wcslib-dev && \ + sudo apt-get autoremove -y + +# +# ******************* +# Pyrap +# ******************* +# +RUN sudo apt-get install -y git make g++ python-setuptools libboost-python-dev libcfitsio3-dev wcslib-dev && \ + mkdir ${INSTALLDIR}/python-casacore && \ + cd ${INSTALLDIR}/python-casacore && git clone https://github.com/casacore/python-casacore && \ + if [ "$PYTHON_CASACORE_VERSION" != "latest" ]; then cd ${INSTALLDIR}/python-casacore/python-casacore && git checkout tags/v${PYTHON_CASACORE_VERSION}; fi && \ + cd ${INSTALLDIR}/python-casacore/python-casacore && ./setup.py build_ext -I${INSTALLDIR}/casacore/include/ -L${INSTALLDIR}/casacore/lib/ && \ + mkdir -p ${INSTALLDIR}/python-casacore/lib/python${PYTHON_VERSION}/site-packages/ && \ + mkdir -p ${INSTALLDIR}/python-casacore/lib64/python${PYTHON_VERSION}/site-packages/ && \ + export PYTHONPATH=${INSTALLDIR}/python-casacore/lib/python${PYTHON_VERSION}/site-packages:${INSTALLDIR}/python-casacore/lib64/python${PYTHON_VERSION}/site-packages:$PYTHONPATH && cd ${INSTALLDIR}/python-casacore/python-casacore && ./setup.py install --prefix=${INSTALLDIR}/python-casacore/ && \ + bash -c "find ${INSTALLDIR}/python-casacore/lib -name '*.so' | xargs strip || true" && \ + bash -c "rm -rf ${INSTALLDIR}/python-casacore/python-casacore" && \ + sudo apt-get purge -y git make g++ python-setuptools libboost-python-dev libcfitsio3-dev wcslib-dev && \ + sudo apt-get autoremove -y + +# +# ******************* +# QPID client +# ******************* +# + +# Allow auto-checkout from lofar repo +RUN mkdir /home/${USER}/.subversion +COPY subversion_servers /home/${USER}/.subversion/servers + +# Run-time dependencies +# QPID daemon legacy store would require: libaio1 libdb5.1++ +RUN sudo apt-get install -y sasl2-bin libuuid1 libnss3 libnspr4 xqilla libboost-program-options${BOOST_VERSION}.0 libboost-filesystem${BOOST_VERSION}.0 + +# Install +# QPID daemon legacy store would require: libaio-dev libdb5.1++-dev +RUN sudo apt-get install -y subversion swig ruby ruby-dev python-dev libsasl2-dev pkg-config cmake libtool uuid-dev libxerces-c-dev libnss3-dev libnspr4-dev help2man fakeroot build-essential debhelper libsslcommon2-dev libxqilla-dev python-setuptools libboost-program-options${BOOST_VERSION}-dev libboost-filesystem${BOOST_VERSION}-dev && \ + mkdir /opt/qpid && \ + svn --non-interactive -q --username lofar-guest --password lofar-guest co ${LOFAR_BRANCH_URL}/LCS/MessageBus/qpid/ /opt/qpid; \ + /opt/qpid/local/sbin/build_qpid && \ + bash -c "strip /opt/qpid/{bin,lib}/* || true" && \ + bash -c "rm -rf ~/sources" && \ + sudo apt-get purge -y subversion swig ruby ruby-dev python-dev libsasl2-dev pkg-config cmake libtool uuid-dev libxerces-c-dev libnss3-dev libnspr4-dev help2man fakeroot build-essential debhelper libsslcommon2-dev libxqilla-dev python-setuptools libboost-program-options${BOOST_VERSION}-dev libboost-filesystem${BOOST_VERSION}-dev && \ + sudo apt-get autoremove -y +# +# ******************* +# DAL +# ******************* +# +RUN sudo apt-get install -y git cmake g++ swig python-dev libhdf5-dev && \ + mkdir ${INSTALLDIR}/DAL && \ + cd ${INSTALLDIR}/DAL && git clone https://github.com/nextgen-astrodata/DAL.git src && \ + mkdir ${INSTALLDIR}/DAL/build && cd ${INSTALLDIR}/DAL/build && cmake -DCMAKE_INSTALL_PREFIX=${INSTALLDIR}/DAL ../src && \ + make -j ${J} && \ + make install && \ + bash -c "find ${INSTALLDIR}/DAL/lib -name '*.so' | xargs strip || true" && \ + bash -c "rm -rf ${INSTALLDIR}/DAL/{src,build}" && \ + sudo apt-get purge -y git cmake g++ swig python-dev libhdf5-dev && \ + sudo apt-get autoremove -y + +# +# config +# +COPY bashrc /home/${USER}/.bashrc + +# +# entry +# +COPY chuser.sh /usr/local/bin/chuser.sh +WORKDIR /home/${USER} +ENTRYPOINT ["sudo","-E","/usr/local/bin/chuser.sh"] + diff --git a/Docker/lofar-base/bashrc b/Docker/lofar-base/bashrc new file mode 100644 index 0000000000000000000000000000000000000000..74dbbeef1254fd1c50e3454a8b19b441379788d1 --- /dev/null +++ b/Docker/lofar-base/bashrc @@ -0,0 +1,13 @@ +#!/bin/bash + +# lofar +[ -r ${INSTALLDIR}/lofar/lofarinit.sh ] && source ${INSTALLDIR}/lofar/lofarinit.sh + +# qpid +source ${INSTALLDIR}/qpid/.profile + +# python-casacore +export PYTHONPATH=${PYTHONPATH}:${INSTALLDIR}/python-casacore/lib/python2.7/site-packages + +# casacore +export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${INSTALLDIR}/casacore/lib diff --git a/Docker/lofar-base/chuser.sh b/Docker/lofar-base/chuser.sh new file mode 100755 index 0000000000000000000000000000000000000000..294e58c7d30e9288aa263d632c738a8ab06c0b98 --- /dev/null +++ b/Docker/lofar-base/chuser.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash + +# Fetch the user name used in this container +export USER=${SUDO_USER} + +if [ -n "${LUSER}" ]; then + if [ -z "${LGROUP}" ]; then + LGROUP=${LUSER} + fi + + OLDID=`id -u ${USER}` + + # Replace USER by LUSER:LGROUP + sed -i -e "s/${USER}:x:[0-9]\+:[0-9]\+/${USER}:x:${LUSER}:${LGROUP}/g" /etc/passwd + sed -i -e "s/${USER}:x:[0-9]\+:/${USER}:x:${LGROUP}:/g" /etc/group + + # Set ownership of home dir to new user + chown --from=${OLDID} -R ${LUSER}:${LGROUP} ${HOME} +fi + +# Switch to the updated user +export HOME=/home/${USER} +touch -a $HOME/.bashrc +sudo -u ${USER} -E -s /bin/bash -c "source $HOME/.bashrc;$*" diff --git a/Docker/lofar-base/subversion_servers b/Docker/lofar-base/subversion_servers new file mode 100644 index 0000000000000000000000000000000000000000..986b312078ec2bdd8474d33f6dce788756d3f609 --- /dev/null +++ b/Docker/lofar-base/subversion_servers @@ -0,0 +1,6 @@ +[groups] +astron = svn.astron.nl + +[astron] +store-passwords = yes +store-plaintext-passwords = yes diff --git a/Docker/lofar-outputproc/Dockerfile.tmpl b/Docker/lofar-outputproc/Dockerfile.tmpl new file mode 100644 index 0000000000000000000000000000000000000000..85474bfcb585b82dc4018a994dfb2322d63263ed --- /dev/null +++ b/Docker/lofar-outputproc/Dockerfile.tmpl @@ -0,0 +1,33 @@ +# +# base +# +FROM lofar-base:${LOFAR_TAG} + +# +# ******************* +# LOFAR +# ******************* +# + +# Run-time dependencies +RUN sudo apt-get install -y liblog4cplus-1.0-4 libxml2 libboost-thread${BOOST_VERSION}.0 libboost-filesystem${BOOST_VERSION}.0 libboost-date-time${BOOST_VERSION}.0 libpng12-0 libsigc++-2.0-dev libxml++2.6-2 libboost-regex${BOOST_VERSION}.0 + +# Tell image build information +ENV LOFAR_BRANCH=${LOFAR_BRANCH_NAME} \ + LOFAR_REVISION=${LOFAR_REVISION} + +# Install +RUN sudo apt-get install -y subversion cmake g++ gfortran bison flex autogen liblog4cplus-dev libhdf5-dev libblitz0-dev libboost-dev libboost-python${BOOST_VERSION}-dev libxml2-dev pkg-config libpng12-dev libfftw3-dev libunittest++-dev libxml++2.6-dev libboost-filesystem${BOOST_VERSION}-dev libboost-date-time${BOOST_VERSION}-dev libboost-thread${BOOST_VERSION}-dev libboost-regex${BOOST_VERSION} binutils-dev && \ + mkdir -p ${INSTALLDIR}/lofar/build/gnu_opt libcfitsio3-dev wcslib-dev && \ + cd ${INSTALLDIR}/lofar && \ + svn --non-interactive -q --username lofar-guest --password lofar-guest co -r ${LOFAR_REVISION} -N ${LOFAR_BRANCH_URL} src; \ + svn --non-interactive -q up src/CMake && \ + cd ${INSTALLDIR}/lofar/build/gnu_opt && cmake -DBUILD_PACKAGES=Online_OutputProc -DCMAKE_INSTALL_PREFIX=${INSTALLDIR}/lofar/ -DCASACORE_ROOT_DIR=${INSTALLDIR}/casacore/ -DLOG4CPLUS_ROOT_DIR=${INSTALLDIR}/log4cplus/ -DQPID_ROOT_DIR=/opt/qpid/ -DDAL_ROOT_DIR=${INSTALLDIR}/DAL -DUSE_OPENMP=True ${INSTALLDIR}/lofar/src/ && \ + cd ${INSTALLDIR}/lofar/build/gnu_opt && sed -i '29,31d' include/ApplCommon/PosixTime.h && \ + cd ${INSTALLDIR}/lofar/build/gnu_opt && make -j ${J} && \ + cd ${INSTALLDIR}/lofar/build/gnu_opt && make install && \ + bash -c "strip ${INSTALLDIR}/lofar/{bin,sbin,lib64}/* || true" && \ + bash -c "rm -rf ${INSTALLDIR}/lofar/{build,src}" && \ + sudo apt-get purge -y subversion cmake g++ gfortran bison flex autogen liblog4cplus-dev libhdf5-dev libblitz0-dev libboost-dev libboost-python${BOOST_VERSION}-dev libxml2-dev pkg-config libpng12-dev libfftw3-dev libunittest++-dev libxml++2.6-dev libboost-filesystem${BOOST_VERSION}-dev libboost-date-time${BOOST_VERSION}-dev libboost-thread${BOOST_VERSION}-dev binutils-dev libcfitsio3-dev wcslib-dev && \ + sudo apt-get autoremove -y + diff --git a/Docker/lofar-pipeline/Dockerfile.tmpl b/Docker/lofar-pipeline/Dockerfile.tmpl new file mode 100644 index 0000000000000000000000000000000000000000..4443b94a15f41ffd3134d6279785e7aa0147983e --- /dev/null +++ b/Docker/lofar-pipeline/Dockerfile.tmpl @@ -0,0 +1,58 @@ +# +# base +# +FROM lofar-base:${LOFAR_TAG} + +ENV AOFLAGGER_VERSION=2.7.1 + +# Run-time dependencies +RUN sudo apt-get install -y python-xmlrunner python-scipy liblog4cplus-1.0-4 libxml2 libboost-thread${BOOST_VERSION}.0 libboost-filesystem${BOOST_VERSION}.0 libboost-date-time${BOOST_VERSION}.0 libboost-signals${BOOST_VERSION}.0 libpng12-0 libsigc++-2.0-dev libxml++2.6-2 libgsl0ldbl openssh-client libboost-regex${BOOST_VERSION}.0 && \ + sudo apt-get -y install python-pip python-dev && \ + sudo pip install pyfits pywcs python-monetdb && \ + sudo apt-get -y purge python-pip python-dev && \ + sudo apt-get -y autoremove + +# +# ******************* +# AOFlagger +# ******************* +# + +RUN sudo apt-get install -y wget cmake g++ libxml++2.6-dev libpng12-dev libfftw3-dev libboost-filesystem${BOOST_VERSION}-dev libboost-date-time${BOOST_VERSION}-dev libboost-signals${BOOST_VERSION}-dev libboost-thread${BOOST_VERSION}-dev libcfitsio3-dev && \ + mkdir -p ${INSTALLDIR}/aoflagger/build && \ + bash -c "cd ${INSTALLDIR}/aoflagger && wget --retry-connrefused http://downloads.sourceforge.net/project/aoflagger/aoflagger-${AOFLAGGER_VERSION%%.?}.0/aoflagger-${AOFLAGGER_VERSION}.tar.bz2" && \ + cd ${INSTALLDIR}/aoflagger && tar xf aoflagger-${AOFLAGGER_VERSION}.tar.bz2 && \ + cd ${INSTALLDIR}/aoflagger/build && cmake -DCASACORE_ROOT_DIR=${INSTALLDIR}/casacore/ -DBUILD_SHARED_LIBS=ON -DCMAKE_INSTALL_PREFIX=${INSTALLDIR}/aoflagger ../aoflagger-${AOFLAGGER_VERSION} && \ + cd ${INSTALLDIR}/aoflagger/build && make -j ${J} && \ + cd ${INSTALLDIR}/aoflagger/build && make install && \ + bash -c "strip ${INSTALLDIR}/aoflagger/{lib,bin}/* || true" && \ + bash -c "rm -rf ${INSTALLDIR}/aoflagger/{build,aoflagger-${AOFLAGGER_VERSION}}" && \ + bash -c "rm -rf ${INSTALLDIR}/aoflagger/aoflagger-${AOFLAGGER_VERSION}.tar.bz2" && \ + sudo apt-get -y purge wget cmake g++ libxml++2.6-dev libpng12-dev libfftw3-dev libboost-filesystem${BOOST_VERSION}-dev libboost-date-time${BOOST_VERSION}-dev libboost-signals${BOOST_VERSION}-dev libboost-thread${BOOST_VERSION}-dev libcfitsio3-dev && \ + sudo apt-get -y autoremove + +# +# ******************* +# LOFAR +# ******************* +# + +# Tell image build information +ENV LOFAR_BRANCH=${LOFAR_BRANCH_NAME} \ + LOFAR_REVISION=${LOFAR_REVISION} + +# Install +RUN sudo apt-get install -y subversion cmake g++ gfortran bison flex liblog4cplus-dev libhdf5-dev libblitz0-dev libboost-dev libboost-python-dev python-dev libxml2-dev pkg-config libpng12-dev libfftw3-dev libunittest++-dev libxml++2.6-dev libgsl0-dev libboost-filesystem${BOOST_VERSION}-dev libboost-date-time${BOOST_VERSION}-dev libboost-thread${BOOST_VERSION}-dev libboost-regex${BOOST_VERSION} binutils-dev libcfitsio3-dev wcslib-dev && \ + mkdir -p ${INSTALLDIR}/lofar/build/gnu_opt && \ + cd ${INSTALLDIR}/lofar && \ + svn --non-interactive -q --username lofar-guest --password lofar-guest co -r ${LOFAR_REVISION} -N ${LOFAR_BRANCH_URL} src; \ + svn --non-interactive -q up src/CMake && \ + cd ${INSTALLDIR}/lofar/build/gnu_opt && cmake -DBUILD_PACKAGES=Offline -DCMAKE_INSTALL_PREFIX=${INSTALLDIR}/lofar/ -DCASAREST_ROOT_DIR=${INSTALLDIR}/casarest/ -DCASACORE_ROOT_DIR=${INSTALLDIR}/casacore/ -DAOFLAGGER_ROOT_DIR=${INSTALLDIR}/aoflagger/ -DLOG4CPLUS_ROOT_DIR=${INSTALLDIR}/log4cplus/ -DQPID_ROOT_DIR=/opt/qpid/ -DUSE_OPENMP=True ${INSTALLDIR}/lofar/src/ && \ + cd ${INSTALLDIR}/lofar/build/gnu_opt && sed -i '29,31d' include/ApplCommon/PosixTime.h && \ + cd ${INSTALLDIR}/lofar/build/gnu_opt && make -j ${J} && \ + cd ${INSTALLDIR}/lofar/build/gnu_opt && make install && \ + bash -c "strip ${INSTALLDIR}/lofar/{bin,sbin,lib64}/* || true" && \ + bash -c "rm -rf ${INSTALLDIR}/lofar/{build,src}" && \ + sudo apt-get purge -y subversion cmake g++ gfortran bison flex liblog4cplus-dev libhdf5-dev libblitz0-dev libboost-dev libboost-python-dev python-dev libxml2-dev pkg-config libpng12-dev libfftw3-dev libunittest++-dev libxml++2.6-dev libgsl0-dev libboost-filesystem${BOOST_VERSION}-dev libboost-date-time${BOOST_VERSION}-dev libboost-thread${BOOST_VERSION}-dev binutils-dev wcslib-dev && \ + sudo apt-get autoremove -y + diff --git a/LCS/Common/include/Common/Version.h b/LCS/Common/include/Common/Version.h index 3e9697c0c402d1f67411dbee067ff166c5edbf2b..3cd389e1ec4677505d62b882abd34c606a03813d 100644 --- a/LCS/Common/include/Common/Version.h +++ b/LCS/Common/include/Common/Version.h @@ -63,6 +63,7 @@ namespace LOFAR { // Construct a Version object from the relevant package info. Version (const std::string& packageName, + const std::string& branch, const std::string& version, const std::string& confVersion, const std::string& revision, @@ -75,6 +76,9 @@ namespace LOFAR { // Get the package name. const std::string& packageName() const { return itsPackageName; } + // Get the LOFAR branch version (relative to repository root) + const std::string& branch() const + { return itsBranch; } // Get the package version (as in repository) const std::string& version() const { return itsVersion; } @@ -195,6 +199,7 @@ namespace LOFAR { //# Data members. std::string itsPackageName; + std::string itsBranch; std::string itsVersion; std::string itsConfVersion; std::string itsRevision; diff --git a/LCS/Common/src/Version.cc b/LCS/Common/src/Version.cc index fd9dd09dc1995236f2df3c9668fcbab1abe10e37..a64c78bf84f081d6beb26800f9cf066bccddab82 100644 --- a/LCS/Common/src/Version.cc +++ b/LCS/Common/src/Version.cc @@ -29,6 +29,7 @@ namespace LOFAR { Version::Version (const std::string& packageName, + const std::string& branch, const std::string& version, const std::string& confVersion, const std::string& revision, @@ -38,6 +39,7 @@ namespace LOFAR { const std::string& buildUser, const std::string& buildMachine) : itsPackageName (packageName), + itsBranch (branch), itsVersion (version), itsConfVersion (confVersion), itsRevision (revision), @@ -129,6 +131,7 @@ namespace LOFAR { os << " (in CMakeLists.txt: " << confVersion() << ')'; } os << std::endl; + os << indent << " branch = " << branch() << std::endl; os << indent << " overall revision = " << revision(); if (!sameRev) os << " (note: used packages have different revision)"; os << std::endl;