@@ -21,13 +21,16 @@ SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
2121print_help () {
2222 echo -e " \nusage: $( basename " $0 " ) [-h] [run] [start] [stop] -- Utility for handling docker in Orbit."
2323 echo -e " \noptional arguments:"
24- echo -e " \t-h, --help Display the help content."
25- echo -e " \tstart Build the docker image and create the container in detached mode."
26- echo -e " \tenter Begin a new bash process within an existing orbit container."
27- echo -e " \tcopy Copy build and logs artifacts from the container to the host machine."
28- echo -e " \tstop Stop the docker container and remove it."
29- echo -e " \tpush Push the docker image to the cluster."
30- echo -e " \tjob Submit a job to the cluster."
24+ echo -e " \t-h, --help Display the help content."
25+ echo -e " \tstart [profile] Build the docker image and create the container in detached mode."
26+ echo -e " \tenter [profile] Begin a new bash process within an existing orbit container."
27+ echo -e " \tcopy [profile] Copy build and logs artifacts from the container to the host machine."
28+ echo -e " \tstop [profile] Stop the docker container and remove it."
29+ echo -e " \tpush [profile] Push the docker image to the cluster."
30+ echo -e " \tjob [profile] [job_args] Submit a job to the cluster."
31+ echo -e " \n"
32+ echo -e " [profile] is the optional container profile specification and [job_args] optional arguments specific"
33+ echo -e " to the executed script"
3134 echo -e " \n" >&2
3235}
3336
@@ -64,12 +67,24 @@ check_docker_version() {
6467resolve_image_extension () {
6568 # If no profile was passed, we default to 'base'
6669 container_profile=${1:- " base" }
70+ # check if the second argument has to be a profile or can be a job argument instead
71+ necessary_profile=${2:- true}
6772
6873 # We also default to 'base' if "orbit" is passed
6974 if [ " $1 " == " orbit" ]; then
7075 container_profile=" base"
7176 fi
7277
78+ # check if a .env.$container_profile file exists
79+ # if the argument is necessary a profile, then the file must exists otherwise an info is printed
80+ if [ " $necessary_profile " = true ] && [ ! -f $SCRIPT_DIR /.env.$container_profile ]; then
81+ echo " [Error] The profile '$container_profile ' has no .env.$container_profile file!" >&2 ;
82+ exit 1
83+ elif [ ! -f $SCRIPT_DIR /.env.$container_profile ]; then
84+ echo " [INFO] No .env.$container_profile found, assume second argument is no profile! Will use default container!" >&2 ;
85+ container_profile=" base"
86+ fi
87+
7388 add_profiles=" --profile $container_profile "
7489 # We will need .env.base regardless of profile
7590 add_envs=" --env-file .env.base"
@@ -92,6 +107,24 @@ is_container_running() {
92107 fi
93108}
94109
110+ # Checks if a docker image exists, otherwise prints warning and exists
111+ check_image_exists () {
112+ image_name=" $1 "
113+ if ! docker image inspect $image_name & > /dev/null; then
114+ echo " [Error] The '$image_name ' image does not exist!" >&2 ;
115+ exit 1
116+ fi
117+ }
118+
119+ # Check if the singularity image exists on the remote host, otherwise print warning and exit
120+ check_singularity_image_exists () {
121+ image_name=" $1 "
122+ if ! ssh " $CLUSTER_LOGIN " " [ -f $CLUSTER_SIF_PATH /$image_name .tar ]" ; then
123+ echo " [Error] The '$image_name ' image does not exist on the remote host $CLUSTER_LOGIN !" >&2 ;
124+ exit 1
125+ fi
126+ }
127+
95128# ==
96129# Main
97130# ==
111144
112145# parse arguments
113146mode=" $1 "
114- resolve_image_extension $2
147+ profile_arg=" $2 " # Capture the second argument as the potential profile argument
148+
149+ # Check mode argument and resolve the container profile
150+ case $mode in
151+ build|start|enter|copy|stop|push)
152+ resolve_image_extension " $profile_arg " true
153+ ;;
154+ job)
155+ resolve_image_extension " $profile_arg " false
156+ ;;
157+ * )
158+ # Not recognized mode
159+ echo " [Error] Invalid command provided: $mode "
160+ print_help
161+ exit 1
162+ ;;
163+ esac
164+
165+ # Produces a nice print statement stating which container profile is being used
166+ echo " [INFO] Using container profile: $container_profile "
167+
115168# resolve mode
116169case $mode in
117170 start)
@@ -169,43 +222,53 @@ case $mode in
169222 if ! command -v apptainer & > /dev/null; then
170223 install_apptainer
171224 fi
225+ # Check if Docker image exists
226+ check_image_exists orbit-$container_profile :latest
172227 # Check if Docker version is greater than 25
173228 check_docker_version
174- # Check if .env.base file exists
175- if [ -f $SCRIPT_DIR /.env.base ]; then
176- # source env file to get cluster login and path information
177- source $SCRIPT_DIR /.env.base
178- # clear old exports
179- rm -rf /$SCRIPT_DIR /exports
180- mkdir -p /$SCRIPT_DIR /exports
181- # create singularity image
182- # NOTE: we create the singularity image as non-root user to allow for more flexibility. If this causes
183- # issues, remove the --fakeroot flag and open an issue on the orbit repository.
184- cd /$SCRIPT_DIR /exports
185- APPTAINER_NOHTTPS=1 apptainer build --sandbox --fakeroot orbit.sif docker-daemon://orbit:latest
186- # tar image and send to cluster
187- tar -cvf /$SCRIPT_DIR /exports/orbit.tar orbit.sif
188- scp /$SCRIPT_DIR /exports/orbit.tar $CLUSTER_LOGIN :$CLUSTER_SIF_PATH /orbit.tar
189- else
190- echo " [Error]: " .env.base" file not found."
191- fi
229+ # source env file to get cluster login and path information
230+ source $SCRIPT_DIR /.env.base
231+ # make sure exports directory exists
232+ mkdir -p /$SCRIPT_DIR /exports
233+ # clear old exports for selected profile
234+ rm -rf /$SCRIPT_DIR /exports/orbit-$container_profile *
235+ # create singularity image
236+ # NOTE: we create the singularity image as non-root user to allow for more flexibility. If this causes
237+ # issues, remove the --fakeroot flag and open an issue on the orbit repository.
238+ cd /$SCRIPT_DIR /exports
239+ APPTAINER_NOHTTPS=1 apptainer build --sandbox --fakeroot orbit-$container_profile .sif docker-daemon://orbit-$container_profile :latest
240+ # tar image (faster to send single file as opposed to directory with many files)
241+ tar -cvf /$SCRIPT_DIR /exports/orbit-$container_profile .tar orbit-$container_profile .sif
242+ # make sure target directory exists
243+ ssh $CLUSTER_LOGIN " mkdir -p $CLUSTER_SIF_PATH "
244+ # send image to cluster
245+ scp $SCRIPT_DIR /exports/orbit-$container_profile .tar $CLUSTER_LOGIN :$CLUSTER_SIF_PATH /orbit-$container_profile .tar
192246 ;;
193247 job)
194- # Check if .env file exists
195- if [ -f $SCRIPT_DIR /.env.base ]; then
196- # Sync orbit code
197- echo " [INFO] Syncing orbit code..."
198- source $SCRIPT_DIR /.env.base
199- rsync -rh --exclude=" *.git*" --filter=' :- .dockerignore' /$SCRIPT_DIR /.. $CLUSTER_LOGIN :$CLUSTER_ORBIT_DIR
200- # execute job script
201- echo " [INFO] Executing job script..."
202- ssh $CLUSTER_LOGIN " cd $CLUSTER_ORBIT_DIR && sbatch $CLUSTER_ORBIT_DIR /docker/cluster/submit_job.sh" " $CLUSTER_ORBIT_DIR " " ${@: 2} "
248+ source $SCRIPT_DIR /.env.base
249+ # Check if singularity image exists on the remote host
250+ check_singularity_image_exists orbit-$container_profile
251+ # make sure target directory exists
252+ ssh $CLUSTER_LOGIN " mkdir -p $CLUSTER_ORBIT_DIR "
253+ # Sync orbit code
254+ echo " [INFO] Syncing orbit code..."
255+ rsync -rh --exclude=" *.git*" --filter=' :- .dockerignore' /$SCRIPT_DIR /.. $CLUSTER_LOGIN :$CLUSTER_ORBIT_DIR
256+ # execute job script
257+ echo " [INFO] Executing job script..."
258+ # check whether the second argument is a profile or a job argument
259+ if [ " $profile_arg " == " $container_profile " ] ; then
260+ # if the second argument is a profile, we have to shift the arguments
261+ echo " [INFO] Arguments passed to job script ${@: 3} "
262+ ssh $CLUSTER_LOGIN " cd $CLUSTER_ORBIT_DIR && sbatch $CLUSTER_ORBIT_DIR /docker/cluster/submit_job.sh" " $CLUSTER_ORBIT_DIR " " orbit-$container_profile " " ${@: 3} "
203263 else
204- echo " [Error]: " .env.base" file not found."
264+ # if the second argument is a job argument, we have to shift only one argument
265+ echo " [INFO] Arguments passed to job script ${@: 2} "
266+ ssh $CLUSTER_LOGIN " cd $CLUSTER_ORBIT_DIR && sbatch $CLUSTER_ORBIT_DIR /docker/cluster/submit_job.sh" " $CLUSTER_ORBIT_DIR " " orbit-$container_profile " " ${@: 2} "
205267 fi
206268 ;;
207269 * )
208- echo " [Error] Invalid argument provided: $1 "
270+ # Not recognized mode
271+ echo " [Error] Invalid command provided: $mode "
209272 print_help
210273 exit 1
211274 ;;
0 commit comments