#!/bin/bash # The MIT License (MIT) # # rootApostolos@swarmlab.io # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. # Origin: https://github.com/NLKNguyen/alpine-mpich set -e DOCKERuser="docker" PACKAGES=" net-tools curl tcpdump shorewall sudo vim nmap dnsutils iputils-ping iptables wget python " APTPARAM=" --no-install-recommends " IMAGE_local="sec" HYBRID_NETWORK="hybrid-sec" # dont edit IMAGE_origin="ubuntu:18.04" bootstrap="sec_bootstrap" hostnames="auto_update_hosts" hostnames_get="get_hosts" # shellcheck disable=SC1091 #. ./.env # ----------------------------------------------- # # Find Source path of swarmlab.io script # # ---------------------------------------------- SOURCE="${BASH_SOURCE[0]}" while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )" SOURCE="$(readlink "$SOURCE")" [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located done DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )" # ----------------------------------------------- # # Load Default config swarmlab.io # # ---------------------------------------------- #. $DIR/.env # ----------------------------------------------- # # Find Working dir # # ---------------------------------------------- Wdir=$(pwd) . $Wdir/.env create_dockerfile () { . $Wdir/ROOT_PASSWORD if [ -d "$Wdir/project" ]; then # ----------------------------------------------- # # create Dockerfile # # ---------------------------------------------- rm -f $Wdir/out.log 2> /dev/null error="Error:"; IMAGE=$(docker inspect --type=image $REGISTRY_ADDR:$REGISTRY_PORT/$IMAGE_NAME:latest 2>&1 | tee $Wdir/out.log) if search=$(grep "$error" $Wdir/out.log) then echo "" echo ">>> Load Origin " cat << EOF > $Wdir/Dockerfile FROM $IMAGE_origin # USER root RUN export DEBIAN_FRONTEND=noninteractive && \ apt-get update && apt-get $APTPARAM install -y openssh-server $PACKAGES RUN apt-get autoremove --purge && apt clean RUN rm -rf /var/lib/apt/lists/* RUN mkdir -p /var/run/sshd RUN echo 'root:$ROOT_PASSWORD' | chpasswd RUN sed -i 's/PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config # # SSH login fix. Otherwise user is kicked off after login RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd # ENV NOTVISIBLE "in users profile" RUN echo "export VISIBLE=now" >> /etc/profile #RUN wget -k https://raw.githubusercontent.com/egalpin/apt-vim/master/install.sh # # # COPY $bootstrap /usr/bin COPY $hostnames_get /usr/bin COPY $hostnames /usr/bin RUN mkdir -p /etc/shorewall COPY shorewall /etc/shorewall RUN mkdir -p /project RUN mkdir -p /etc/opt WORKDIR /project COPY install-vim-plugin.sh . #RUN bash ./install-vim-plugin.sh #RUN apt-vim install -y https://github.com/scrooloose/nerdtree.git RUN grep -qw ^docker /etc/passwd || useradd -m docker && echo "docker:docker" | chpasswd && adduser docker sudo COPY .vimrc /home/docker USER docker EOF else echo ">>> Load Local " cat << EOF > $Wdir/Dockerfile FROM localhost:5000/$IMAGE_local # USER root RUN export DEBIAN_FRONTEND=noninteractive && \ apt-get update && apt-get $APTPARAM install -y openssh-server $PACKAGES RUN apt-get autoremove --purge && apt clean RUN rm -rf /var/lib/apt/lists/* RUN mkdir -p /var/run/sshd RUN echo 'root:$ROOT_PASSWORD' | chpasswd RUN sed -i 's/PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config # # SSH login fix. Otherwise user is kicked off after login RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd # ENV NOTVISIBLE "in users profile" RUN echo "export VISIBLE=now" >> /etc/profile #RUN wget -k https://raw.githubusercontent.com/egalpin/apt-vim/master/install.sh # # # COPY $bootstrap /usr/bin COPY $hostnames_get /usr/bin COPY $hostnames /usr/bin RUN mkdir -p /etc/shorewall COPY shorewall /etc/shorewall RUN mkdir -p /etc/opt RUN mkdir -p /project WORKDIR /project COPY install-vim-plugin.sh . #RUN bash ./install-vim-plugin.sh #RUN apt-vim install -y https://github.com/scrooloose/nerdtree.git RUN grep -qw ^docker /etc/passwd || useradd -m docker && echo "docker:docker" | chpasswd && adduser docker sudo COPY .vimrc /home/docker USER docker EOF fi else echo "" echo "Not in Project Directory" echo "A project directory should look like this" echo "" cat < /dev/null error="Error:"; IMAGE=$(docker inspect --type=image $REGISTRY_ADDR:$REGISTRY_PORT/$IMAGE_NAME:latest 2>&1 | tee $Wdir/out.log) if search=$(grep "$error" $Wdir/out.log) then echo ">>> Load Origin " cat << EOF > $Wdir/Dockerfile FROM $IMAGE_origin # USER root RUN export DEBIAN_FRONTEND=noninteractive && \ apt-get update && apt-get $APTPARAM install -y openssh-server $PACKAGES RUN apt-get autoremove --purge && apt clean RUN rm -rf /var/lib/apt/lists/* RUN mkdir -p /var/run/sshd RUN echo 'root:$ROOT_PASSWORD' | chpasswd RUN sed -i 's/PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config # # SSH login fix. Otherwise user is kicked off after login RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd # ENV NOTVISIBLE "in users profile" RUN echo "export VISIBLE=now" >> /etc/profile #RUN wget -k https://raw.githubusercontent.com/egalpin/apt-vim/master/install.sh # # # COPY $bootstrap /usr/bin COPY $hostnames_get /usr/bin COPY $hostnames /usr/bin RUN mkdir -p /etc/shorewall COPY shorewall /etc/shorewall RUN mkdir -p /etc/opt RUN mkdir -p /project WORKDIR /project COPY install-vim-plugin.sh . #RUN bash ./install-vim-plugin.sh #RUN apt-vim install -y https://github.com/scrooloose/nerdtree.git CMD export PATH=$PATH:/project RUN grep -qw ^docker /etc/passwd || useradd -m docker && echo "docker:docker" | chpasswd && adduser docker sudo COPY .vimrc /home/docker USER docker EOF else echo ">>> Load Local " cat << EOF > $Wdir/Dockerfile FROM localhost:5000/$IMAGE_local # USER root RUN export DEBIAN_FRONTEND=noninteractive && \ apt-get update && apt-get $APTPARAM install -y openssh-server $PACKAGES RUN apt-get autoremove --purge && apt clean RUN rm -rf /var/lib/apt/lists/* RUN mkdir -p /var/run/sshd RUN echo 'root:$ROOT_PASSWORD' | chpasswd RUN sed -i 's/PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config # # SSH login fix. Otherwise user is kicked off after login RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd # ENV NOTVISIBLE "in users profile" RUN echo "export VISIBLE=now" >> /etc/profile #RUN wget -k https://raw.githubusercontent.com/egalpin/apt-vim/master/install.sh # # # COPY $bootstrap /usr/bin COPY $hostnames_get /usr/bin COPY $hostnames /usr/bin RUN mkdir -p /etc/shorewall COPY shorewall /etc/shorewall RUN mkdir -p /etc/opt RUN mkdir -p /project WORKDIR /project COPY install-vim-plugin.sh . #RUN bash ./install-vim-plugin.sh #RUN apt-vim install -y https://github.com/scrooloose/nerdtree.git CMD export PATH=$PATH:/project RUN grep -qw ^docker /etc/passwd || useradd -m docker && echo "docker:docker" | chpasswd && adduser docker sudo COPY .vimrc /home/docker USER docker EOF fi /bin/mkdir -p $Wdir/project /bin/cp -f $DIR/project/hello_world.sh $Wdir/project /bin/cp -f $DIR/$bootstrap $Wdir/$bootstrap /bin/cp -f $DIR/$hostnames $Wdir/$hostnames /bin/cp -f $DIR/$hostnames_get $Wdir/$hostnames_get /bin/cp -f $DIR/ROOT_PASSWORD $Wdir/ROOT_PASSWORD /bin/cp -rf $DIR/shorewall $Wdir/shorewall /bin/cp -rf $DIR/.vimrc $Wdir/.vimrc /bin/cp -rf $DIR/install-vim-plugin.sh $Wdir/install-vim-plugin.sh cat << EOF > $Wdir/docker-compose.yml version: "2" services: registry: image: registry ports: - "${REGISTRY_PORT}:5000" master: image: $REGISTRY_ADDR:$REGISTRY_PORT/$IMAGE_NAME privileged: true cap_add: - NET_ADMIN user: root entrypoint: ["sec_bootstrap", "role=master", "sec_master_service_name=master", "sec_worker_service_name=worker"] ports: - "\${SSH_PORT}:22" networks: - ${HYBRID_NETWORK} volumes: - $Wdir/project:/project worker: image: $REGISTRY_ADDR:$REGISTRY_PORT/$IMAGE_NAME privileged: true cap_add: - NET_ADMIN user: root entrypoint: ["sec_bootstrap", "role=worker", "sec_master_service_name=master", "sec_worker_service_name=worker"] networks: - ${HYBRID_NETWORK} volumes: - $Wdir/project:/project networks: ${HYBRID_NETWORK}: EOF /bin/cp -rf $DIR/ssh $Wdir cat < CLEAN UP SWARMLAB" printf "\\n%s\\n" "$HEADER" echo "$ docker-compose down" printf "\\n" docker-compose down } up_registry () { printf "\\n\\n===> SPIN UP REGISTRY" printf "\\n%s\\n" "$HEADER" echo "$ docker-compose up -d registry" printf "\\n" #docker stop swarmlab-registry || true && docker rm swarmlab-registry || true docker container prune --force docker-compose up --no-recreate -d registry } generate_ssh_keys () { if [ -f ssh/id_rsa ] && [ -f ssh/id_rsa.pub ]; then return 0 fi printf "\\n\\n===> GENERATE SSH KEYS \\n\\n" echo "$ mkdir -p ssh/ " printf "\\n" mkdir -p ssh/ echo "$ ssh-keygen -f ssh/id_rsa -t rsa -N ''" printf "\\n" ssh-keygen -f ssh/id_rsa -t rsa -N '' } build_and_push_image () { printf "\\n\\n===> BUILD IMAGE" printf "\\n%s\\n" "$HEADER" echo "$ docker build -t \"$REGISTRY_ADDR:$REGISTRY_PORT/$IMAGE_NAME\" ." printf "\\n" docker build -t "$REGISTRY_ADDR:$REGISTRY_PORT/$IMAGE_NAME" . printf "\\n" printf "\\n\\n===> PUSH IMAGE TO REGISTRY" printf "\\n%s\\n" "$HEADER" echo "$ docker push \"$REGISTRY_ADDR:$REGISTRY_PORT/$IMAGE_NAME\"" printf "\\n" docker push "$REGISTRY_ADDR:$REGISTRY_PORT/$IMAGE_NAME" } up_master () { printf "\\n\\n===> SPIN UP MASTER NODE" printf "\\n%s\\n" "$HEADER" echo "$ docker-compose up -d master" printf "\\n" docker-compose up -d master } up_workers () { printf "\\n\\n===> SPIN UP WORKER NODES" printf "\\n%s\\n" "$HEADER" echo "$ docker-compose up -d worker" printf "\\n" docker-compose up -d worker printf "\\n" printf "\\n%s\\n" "$HEADER" NUM_WORKER=$((SIZE - 1)) echo "$ docker-compose scale worker=$NUM_WORKER" printf "\\n" docker-compose scale worker=${NUM_WORKER} } down_master () { printf "\\n\\n===> TORN DOWN MASTER NODE" printf "\\n%s\\n" "$HEADER" echo "$ docker-compose stop master && docker-compose rm -f master" printf "\\n" docker-compose stop master && docker-compose rm -f master } down_workers () { printf "\\n\\n===> TORN DOWN WORKER NODES" printf "\\n%s\\n" "$HEADER" echo "$ docker-compose stop worker && docker-compose rm -f worker" printf "\\n" docker-compose stop worker && docker-compose rm -f worker } list () { printf "\\n\\n===> LIST CONTAINERS" printf "\\n%s\\n" "$HEADER" echo "$ docker-compose ps" printf "\\n" docker-compose ps } exec_on_mpi_master_container () { # shellcheck disable=SC2046 docker exec -it -u $DOCKERuser $(docker-compose ps | grep 'master'| awk 'NR==1{print $1}') "$@" } prompt_ready () { printf "\\n\\n===> SWARMLAB READY \\n\\n" } show_instruction () { echo ' ## . ' echo ' ## ## ## == ' echo ' ## ## ## ## ## === ' echo ' /"""""""""""""""""\___/ === ' echo ' ~~~ {~~ ~~~~ ~~~ ~~~~ ~~~ ~ / ===- ~~~ ' echo ' \______ o __/ ' echo ' \ \ __/ ' echo ' \____\_______/ ' echo ' ' echo ' Swarmlab.io Hybrid ' echo '' echo '==============================================================' echo '' echo "To run SEC programs in an interative shell:" echo " 1. Login to master node:" echo " Using Docker through command wrapper:" echo " $ swarmlab-sec login" echo "" echo " Or using SSH with keys through exposed port:" echo " $ ssh -o \"StrictHostKeyChecking no\" -i ssh/id_rsa -p $SSH_PORT sec@localhost" echo ' where [localhost] could be changed to the host IP of master node' echo "" echo " 2. Execute programs inside master node, for example:" echo " $ sudo su" echo " # apt update" echo " *----------------------------------------------------*" echo " | Default hostfile of connected nodes in the swarmlab |" echo " | is automatically updated at /etc/opt/hosts |" echo " | To obtain hostfile manually: $ get_hosts > hosts |" echo " * ---------------------------------------------------*" echo "" echo "" } ############################################# while [ "$1" != "" ]; do PARAM=$(echo "$1" | awk -F= '{print $1}') VALUE=$(echo "$1" | awk -F= '{print $2}') case $PARAM in help) usage exit ;; -i) show_instruction exit ;; login) COMMAND_LOGIN=1 ;; exec) COMMAND_EXEC=1 shift # the rest is the shell command to run in the node SHELL_COMMAND="$*" break # end while loop ;; up) COMMAND_UP=1 ;; create) COMMAND_CREATE=1 ;; down) COMMAND_DOWN=1 ;; reload) COMMAND_RELOAD=1 ;; scale) COMMAND_SCALE=1 ;; list) COMMAND_LIST=1 ;; clean) COMMAND_CLEAN=1 ;; size) [ "$VALUE" ] && SIZE=$VALUE ;; *) echo "ERROR: unknown parameter \"$PARAM\"" usage exit 1 ;; esac shift done if [ $COMMAND_UP -eq 1 ]; then create_dockerfile down_all clear_all up_registry generate_ssh_keys build_and_push_image up_master up_workers prompt_ready show_instruction elif [ $COMMAND_CREATE -eq 1 ]; then create_project elif [ $COMMAND_DOWN -eq 1 ]; then down_all clear_all elif [ $COMMAND_CLEAN -eq 1 ]; then clear_all elif [ $COMMAND_SCALE -eq 1 ]; then create_dockerfile down_master down_workers up_master up_workers prompt_ready show_instruction elif [ $COMMAND_RELOAD -eq 1 ]; then create_dockerfile down_master down_workers build_and_push_image up_master up_workers prompt_ready show_instruction elif [ $COMMAND_LOGIN -eq 1 ]; then exec_on_mpi_master_container /bin/bash elif [ $COMMAND_EXEC -eq 1 ]; then create_dockerfile exec_on_mpi_master_container ash -c "${SHELL_COMMAND}" elif [ $COMMAND_LIST -eq 1 ]; then list else usage fi