Skip to content

Commit a757be1

Browse files
committed
Airflow translator testing
Dockerfile updates setup.py fix
1 parent 1cd259d commit a757be1

5 files changed

Lines changed: 85 additions & 44 deletions

File tree

setup.py

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@
99
# (at your option) any later version.
1010

1111
import sys
12+
import os
13+
import stat
14+
import shutil
15+
import site
16+
import sysconfig
1217
import subprocess
1318

1419
from setuptools import setup, find_packages
@@ -25,16 +30,28 @@ def run(self):
2530
sys.exit(-1)
2631
super().run()
2732

33+
# Do a by-hand copy of cpu-benchmark to the bin directory, as this is so
34+
# hard to do using data_file in the setup() declaration
35+
scripts_dir = os.path.join(site.USER_BASE, "bin")
36+
source_path = os.path.join("bin", "cpu-benchmark")
37+
target_path = os.path.join(scripts_dir, "cpu-benchmark")
38+
# Ensure it's executable (just in case)
39+
st = os.stat(source_path)
40+
os.chmod(source_path, st.st_mode | stat.S_IEXEC)
41+
# Copy to scripts directory
42+
shutil.copy2(source_path, target_path)
43+
2844
setup(
2945
packages=find_packages(),
3046
include_package_data=True,
3147
has_ext_modules=lambda: True,
3248
cmdclass={
3349
'build_ext': Build,
3450
},
35-
data_files=[
36-
('bin', ['bin/cpu-benchmark', 'bin/wfbench'])
37-
],
51+
#data_files=[
52+
# (user_bin_dir, ['bin/cpu-benchmark'])
53+
#],
54+
scripts=['bin/wfbench'],
3855
entry_points={
3956
'console_scripts': [
4057
'wfchef=wfcommons.wfchef.chef:main'

tests/translators/Dockerfile.airflow

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ RUN update-alternatives --install /usr/bin/python python /usr/bin/python3 1
3434
RUN apt-get -y install stress-ng
3535

3636
# WfCommons
37-
RUN python3 -m pip install --break-system-packages wfcommons
37+
#RUN python3 -m pip install --break-system-packages wfcommons
3838

3939
# Install Airflow
4040
RUN python3 -m pip install --break-system-packages apache-airflow==2.10.2 --constraint "https://raw.githubusercontent.com/apache/airflow/constraints-2.10.2/constraints-3.12.txt"
@@ -48,8 +48,11 @@ RUN python3 -m pip install --break-system-packages mysqlclient
4848
# Setup directory
4949
RUN mkdir /home/wfcommons
5050

51-
# Create an entrypoint script to start mysqld in the background
52-
# and setup the Airflow DB
51+
# Create an entrypoint script to start mysqld in the background and setup the Airflow DB
52+
# This script is then used as the entry points of this Container
53+
# Create ALSO a script to run a benchmark (only the last line differ), which is used for testing,
54+
# because using docker-py, things get complicated with different bash sessions!
55+
5356
RUN echo '#!/bin/bash' > /entrypoint.sh && \
5457
echo 'mysqld --explicit-defaults-for-timestamp &' >> /entrypoint.sh && \
5558
echo 'until mysqladmin ping -h localhost --silent; do' >> /entrypoint.sh && \
@@ -66,10 +69,16 @@ RUN echo '#!/bin/bash' > /entrypoint.sh && \
6669
echo "sed -i ./airflow/airflow.cfg -e 's/sqlite:.*/mysql+mysqldb:\/\/airflow_user:airflow_pass@localhost:3306\/airflow_db/'" >> /entrypoint.sh && \
6770
echo 'airflow db migrate' >> /entrypoint.sh && \
6871
echo 'echo "Airflow database setup!"' >> /entrypoint.sh && \
69-
echo 'mkdir ./airflow/dags' >> /entrypoint.sh && \
70-
echo 'exec bash' >> /entrypoint.sh && \
72+
echo 'mkdir ./airflow/dags' >> /entrypoint.sh
73+
74+
RUN cp /entrypoint.sh /run_a_workflow.sh
75+
76+
RUN echo 'exec bash' >> /entrypoint.sh && \
7177
chmod +x /entrypoint.sh
7278

79+
RUN echo 'airflow dags test $1' >> /run_a_workflow.sh && \
80+
chmod +x /run_a_workflow.sh
81+
7382
WORKDIR /home/wfcommons
7483

7584
ENTRYPOINT ["/entrypoint.sh"]

tests/translators/README.airflow

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ A much simpler alternative is to use Docker.
5858
2. Run the docker container in the directory to contains the translated
5959
workflow (see last section below)
6060

61-
docker run -it --rm -v .:/home/wfcommons/mount wfcommons-dev /bin/bash
61+
docker run -it --rm -v .:/home/wfcommons/translated_workflow wfcommons-dev /bin/bash
6262

6363

6464
Running a translated workflow with Airflow
@@ -83,11 +83,12 @@ translator = AirflowTranslator(benchmark.workflow)
8383
translator.translate(output_folder=pathlib.Path("/tmp/translated_workflow/"))
8484
```
8585

86-
The above will create a JSON worfklow file in /tmp/blast-benchmark-45.json.
86+
The above will create a JSON workflow file in /tmp/blast-benchmark-45.json.
8787
In that file, the workflow name (this is used below) is set to "Blast-Benchmark".
8888

8989
The above will also create the translated workflow the
90-
/tmp/translated_workflow/ directory. Some directories and files need to be copied/moved as follows:
90+
/tmp/translated_workflow/ directory. Some directories and files need to be copied/moved as follows.
91+
As
9192

9293
cp -r /tmp/translated_workflow/ $AIRFLOW_HOME/dags/
9394
mv $AIRFLOW_HOME/dags/translated_workflow/workflow.py $AIRFLOW_HOME/dags/
@@ -97,4 +98,6 @@ Finally, run the workflow as:
9798
airflow dags test Blast-Benchmark (note the "Blast-Benchmark" workflow name from above)
9899

99100

101+
Note that if you're using docker, the above two commands need to be done on the container,
102+
with the right paths (i.e., /home/wfcommons/translated_workflow instead of /tmp/translated_workflow/)
100103

tests/translators/test_translators.py

Lines changed: 42 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
from wfcommons.wfbench import AirflowTranslator
2727

2828

29-
def start_docker_container(backend, working_dir):
29+
def start_docker_container(backend, mounted_dir, working_dir, command = ["sleep", "infinity"]):
3030
# Pulling the Docker image
3131
client = docker.from_env()
3232
sys.stderr.write("Pulling Docker image...\n")
@@ -43,8 +43,8 @@ def start_docker_container(backend, working_dir):
4343
sys.stderr.write("Starting Docker container...\n")
4444
container = client.containers.run(
4545
image_name,
46-
"sleep infinity",
47-
volumes={working_dir: {'bind': working_dir, 'mode': 'rw'}},
46+
command=command,
47+
volumes={mounted_dir: {'bind': mounted_dir, 'mode': 'rw'}},
4848
working_dir=working_dir,
4949
tty=True,
5050
detach=True
@@ -91,7 +91,7 @@ def create_workflow_benchmark():
9191
class TestTranslators:
9292

9393
@pytest.mark.unit
94-
@pytest.mark.skip(reason="tmp")
94+
# @pytest.mark.skip(reason="tmp")
9595
def test_dask_translator(self) -> None:
9696

9797
# Create workflow benchmark
@@ -109,12 +109,12 @@ def test_dask_translator(self) -> None:
109109
translator.translate(output_folder=dirpath)
110110

111111
# Pulling the Docker image
112-
container = start_docker_container("dask", str_dirpath)
112+
container = start_docker_container("dask", str_dirpath, str_dirpath)
113113

114114
# Installing WfCommons on container
115115
install_WfCommons_on_container(container)
116116

117-
# Copy over the wfbench and cpu-benchmark executables to where they should go
117+
# Copy over the wfbench and cpu-benchmark executables to where they should go on the container
118118
exit_code, output = container.exec_run("sudo cp -f /tmp/WfCommons/bin/wfbench " + str_dirpath + "bin/", stdout=True, stderr=True)
119119
exit_code, output = container.exec_run("sudo cp -f /tmp/WfCommons/bin/cpu-benchmark " + str_dirpath + "bin/", stdout=True, stderr=True)
120120

@@ -134,7 +134,7 @@ def test_dask_translator(self) -> None:
134134

135135

136136
@pytest.mark.unit
137-
@pytest.mark.skip(reason="tmp")
137+
# @pytest.mark.skip(reason="tmp")
138138
def test_parsl_translator(self) -> None:
139139

140140
# Create workflow benchmark
@@ -151,8 +151,8 @@ def test_parsl_translator(self) -> None:
151151
translator = ParslTranslator(benchmark.workflow)
152152
translator.translate(output_folder=dirpath)
153153

154-
# Pulling the Docker image
155-
container = start_docker_container("parsl", str_dirpath)
154+
# Starting the Docker container
155+
container = start_docker_container("parsl", str_dirpath, str_dirpath)
156156

157157
# Installing WfCommons on container
158158
install_WfCommons_on_container(container)
@@ -178,7 +178,7 @@ def test_parsl_translator(self) -> None:
178178
assert(num_completed_tasks == num_tasks)
179179

180180
@pytest.mark.unit
181-
@pytest.mark.skip(reason="tmp")
181+
# @pytest.mark.skip(reason="tmp")
182182
def test_nextflow_translator(self) -> None:
183183

184184
# Create workflow benchmark
@@ -195,8 +195,8 @@ def test_nextflow_translator(self) -> None:
195195
translator = NextflowTranslator(benchmark.workflow)
196196
translator.translate(output_folder=dirpath)
197197

198-
# Pulling the Docker image
199-
container = start_docker_container("nextflow", str_dirpath)
198+
# Starting the Docker container
199+
container = start_docker_container("nextflow", str_dirpath, str_dirpath)
200200

201201
# Installing WfCommons on container
202202
install_WfCommons_on_container(container)
@@ -222,7 +222,7 @@ def test_nextflow_translator(self) -> None:
222222

223223

224224
@pytest.mark.unit
225-
@pytest.mark.skip(reason="tmp")
225+
# @pytest.mark.skip(reason="tmp")
226226
def test_airflow_translator(self) -> None:
227227

228228
# Create workflow benchmark
@@ -239,27 +239,37 @@ def test_airflow_translator(self) -> None:
239239
translator = AirflowTranslator(benchmark.workflow)
240240
translator.translate(output_folder=dirpath)
241241

242-
# Pulling the Docker image
243-
container = start_docker_container("airflow", str_dirpath)
242+
# Starting the Docker container
243+
container = start_docker_container("airflow", str_dirpath, "/home/wfcommons/", command=None)
244+
# container = start_docker_container("airflow", str_dirpath, "/home/wfcommons/")
244245

245246
# Installing WfCommons on container
246247
install_WfCommons_on_container(container)
247248

249+
248250
# Copy over the wfbench and cpu-benchmark executables to where they should go
249-
# exit_code, output = container.exec_run("sudo cp -f /tmp/WfCommons/bin/wfbench " + str_dirpath + "bin/",
250-
# stdout=True, stderr=True)
251-
# exit_code, output = container.exec_run("sudo cp -f /tmp/WfCommons/bin/cpu-benchmark " + str_dirpath + "bin/",
252-
# stdout=True, stderr=True)
253-
#
254-
# # Run the workflow!
255-
# sys.stderr.write("Running the Airflow workflow on the container...\n")
256-
# exit_code, output = container.exec_run(f"nextflow run ./workflow.nf --pwd .", stdout=True, stderr=True)
257-
# ignored, task_exit_codes = container.exec_run("find . -name .exitcode -exec cat {} \;", stdout=True, stderr=True)
258-
#
259-
# # Kill the container
260-
# container.remove(force=True)
261-
#
262-
# # Do sanity checks
263-
# sys.stderr.write("Checking sanity...\n")
264-
# assert (exit_code == 0)
265-
# assert (task_exit_codes.decode() == num_tasks * "0")
251+
exit_code, output = container.exec_run("sudo cp -f /tmp/WfCommons/bin/wfbench /usr/local/bin/",
252+
stdout=True, stderr=True)
253+
exit_code, output = container.exec_run("sudo cp -f /tmp/WfCommons/bin/cpu-benchmark /usr/local/bin/",
254+
stdout=True, stderr=True)
255+
256+
# Do the necessary copies (some ugly hardcoded stuff here)
257+
airflow_home = "/home/wfcommons/airflow/" # per the Dockerfile
258+
exit_code, output = container.exec_run(f"cp -r /tmp/airflow_translated_workflow {airflow_home}/dags/",stdout=True, stderr=True)
259+
exit_code, output = container.exec_run(f"mv {airflow_home}/dags/airflow_translated_workflow/workflow.py {airflow_home}/dags/",stdout=True, stderr=True)
260+
261+
# # Run the entry point script by hand (such a hack!)
262+
# exit_code, output = container.exec_run(f"/bin/bash /entrypoint.sh",stdout=True, stderr=True)
263+
# print(output)
264+
265+
# Run the workflow!
266+
sys.stderr.write("Running the Airflow workflow on the container...\n")
267+
exit_code, output = container.exec_run(cmd="/bin/bash /run_a_workflow.sh Blast-Benchmark", stdout=True, stderr=True)
268+
269+
# Kill the container
270+
container.remove(force=True)
271+
272+
# Do sanity checks
273+
sys.stderr.write("Checking sanity...\n")
274+
assert (exit_code == 0)
275+
assert (output.decode().count("completed") == num_tasks * 2)

wfcommons/wfbench/translator/abstract_translator.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import logging
1212
import os
1313
import sys
14+
import site
1415
import pathlib
1516
import shutil
1617
import textwrap
@@ -92,7 +93,8 @@ def _copy_binary_files(self, output_folder: pathlib.Path) -> None:
9293
bin_folder = output_folder.joinpath("bin")
9394
bin_folder.mkdir(exist_ok=True)
9495
# Get the python executable dir
95-
python_executable_dir = os.path.dirname(sys.executable)
96+
# python_executable_dir = os.path.dirname(sys.executable)
97+
python_executable_dir = os.path.join(site.getuserbase(), 'bin')
9698
# shutil.copy(shutil.which("wfbench"), bin_folder)
9799
shutil.copy(python_executable_dir + "/wfbench", bin_folder)
98100
# shutil.copy(shutil.which("cpu-benchmark"), bin_folder)

0 commit comments

Comments
 (0)