From f89a660bfa1c3162eeb44040a47eed181016ac58 Mon Sep 17 00:00:00 2001 From: amitlissack Date: Thu, 27 May 2021 11:38:21 -0400 Subject: [PATCH] feat(api,robot-server): Add Dockerfile and docker-compose file (#7836) * docker file. * docker-compose * Controller will build simulating gpio object so no reason for the check. * Update docker-compose.yml Co-authored-by: Sam! Bonfante <6620407+X-sam@users.noreply.github.com> * Update docker-compose.yml Co-authored-by: Sam! Bonfante <6620407+X-sam@users.noreply.github.com> * override config dir * only copy files needed for the build. * need manifest * added readme. * formatter Co-authored-by: Sam! Bonfante <6620407+X-sam@users.noreply.github.com> closes #7674 --- .dockerignore | 38 +++++++++++++++++++ .opentrons_config/config.json | 18 +++++++++ .opentrons_config/feature_flags.json | 17 +++++++++ .../pipettes/P20SV202020070101.json | 1 + .../pipettes/P3HMV202020041605.json | 1 + CONTRIBUTING.md | 2 +- DOCKER.md | 28 ++++++++++++++ Dockerfile | 29 ++++++++++++++ api/MANIFEST.in | 1 - .../opentrons/hardware_control/controller.py | 17 ++++----- .../hardware_control/emulation/app.py | 2 +- docker-compose.yml | 27 +++++++++++++ robot-server/setup.py | 4 ++ 13 files changed, 173 insertions(+), 12 deletions(-) create mode 100644 .dockerignore create mode 100644 .opentrons_config/config.json create mode 100644 .opentrons_config/feature_flags.json create mode 100644 .opentrons_config/pipettes/P20SV202020070101.json create mode 100644 .opentrons_config/pipettes/P3HMV202020041605.json create mode 100644 DOCKER.md create mode 100644 Dockerfile create mode 100644 docker-compose.yml diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000000..4073f078f70 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,38 @@ +./api-server +./app +./labware-library +./node_modules +./protocol-designer +./discovery-client +./coverage +./components +./app-shell +./update-server +./step-generation + +.pytest_cache +.flake8 +.idea +.pypy_cache +dist +build +yarn.lock +Pipfile.lock + +__pycache__ +*.pyc +*.pyo +*.pyd +.Python +env +pip-log.txt +pip-delete-this-directory.txt +.tox +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*,cover +*.log +.git diff --git a/.opentrons_config/config.json b/.opentrons_config/config.json new file mode 100644 index 00000000000..51ba27f79c8 --- /dev/null +++ b/.opentrons_config/config.json @@ -0,0 +1,18 @@ +{ + "labware_database_file": "/config/opentrons.db", + "labware_calibration_offsets_dir_v2": "/config/labware/v2/offsets", + "labware_user_definitions_dir_v2": "/config/labware/v2/custom_definitions", + "feature_flags_file": "/config/feature_flags.json", + "robot_settings_file": "/config/robot_settings.json", + "deck_calibration_file": "/config/deck_calibration.json", + "log_dir": "/config/logs", + "api_log_file": "/config/logs/api.log", + "serial_log_file": "/config/logs/serial.log", + "wifi_keys_dir": "/config/user_storage/opentrons_data/network_keys", + "hardware_controller_lockfile": "/config/hardware.lock", + "pipette_config_overrides_dir": "/config/pipettes", + "tip_length_calibration_dir": "/config/tip_lengths", + "robot_calibration_dir": "/config/robot", + "pipette_calibration_dir": "/config/robot/pipettes", + "custom_tiprack_dir": "/config/tip_lengths/custom_tiprack_definitions" +} diff --git a/.opentrons_config/feature_flags.json b/.opentrons_config/feature_flags.json new file mode 100644 index 00000000000..f5790b92b4a --- /dev/null +++ b/.opentrons_config/feature_flags.json @@ -0,0 +1,17 @@ +{ + "shortFixedTrash": null, + "calibrateToBottom": null, + "deckCalibrationDots": null, + "useProtocolApi2": null, + "disableHomeOnBoot": null, + "useOldAspirationFunctions": null, + "enableDoorSafetySwitch": null, + "enableTipLengthCalibration": null, + "enableHttpProtocolSessions": null, + "enableFastProtocolUpload": null, + "enableProtocolEngine": null, + "disableLogAggregation": null, + "enableApi1BackCompat": null, + "useV1HttpApi": null, + "_version": 9 +} diff --git a/.opentrons_config/pipettes/P20SV202020070101.json b/.opentrons_config/pipettes/P20SV202020070101.json new file mode 100644 index 00000000000..8a711547564 --- /dev/null +++ b/.opentrons_config/pipettes/P20SV202020070101.json @@ -0,0 +1 @@ +{ "model": "p20_single_v2.0" } diff --git a/.opentrons_config/pipettes/P3HMV202020041605.json b/.opentrons_config/pipettes/P3HMV202020041605.json new file mode 100644 index 00000000000..0f7593543a0 --- /dev/null +++ b/.opentrons_config/pipettes/P3HMV202020041605.json @@ -0,0 +1 @@ +{ "model": "p20_multi_v2.0" } diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d7b9388d0cd..e289a013e1c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,4 +1,3 @@ - # Contributing Guide Thanks for your interest in contributing to the Opentrons platform! This Contributing Guide is intended to ensure best practices for both internal Opentrons contributors as well as any external contributors. We want to make sure you’re set up to contribute effectively, no matter if you’re helping us out with bug reports, code, documentation, feature suggestions, or anything else. This guide covers: @@ -150,6 +149,7 @@ Your computer will need the following tools installed to be able to develop with ``` **MacOS Big Sur Note:** due to this [known issue](https://github.com/pyenv/pyenv/issues/1737) we recommend using: + ```shell pyenv install 3.7.10 ``` diff --git a/DOCKER.md b/DOCKER.md new file mode 100644 index 00000000000..aac2c436434 --- /dev/null +++ b/DOCKER.md @@ -0,0 +1,28 @@ +Docker Guide +======================= +Included in this repo are the tools to run a containerized Opentrons robot stack in docker. + +This includes the `robot-server` connected to the hardware emulation application. The emulation application includes the Smoothie and magnetic, temperature, and thermocycler modules. + +## Requirements + +- A clone of this repo. +- An installation [docker](https://docs.docker.com/get-docker/) +- An installation of [docker-compose](https://docs.docker.com/compose/install/) + +## How to use + +Start a terminal and change directory to the root of this repo. + +1. Build + Enter `docker-compose build --force-rm` at the terminal. + +2. Run + Enter `docker-compose up` at the terminal. _The build and run stages can be combined `docker-compose up --build`._ + +3. Start the Opentrons application. The docker container will appear as `dev`. Connect and run just as you would on a robot. + +## Known Issues + +- Pipettes cannot be changed at run time. +- Pipettes are fixed as `p20_multi_v2.0` on the left mount and `p20_single_v2.0` on the right. diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000000..5f2bd4a9443 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,29 @@ +FROM ubuntu as base +RUN apt-get update && apt-get install -y python3 pip + +FROM base as builder +COPY scripts scripts +COPY LICENSE LICENSE + +COPY shared-data shared-data + +COPY api/MANIFEST.in api/MANIFEST.in +COPY api/setup.py api/setup.py +COPY api/pypi-readme.rst api/pypi-readme.rst +COPY api/src/opentrons api/src/opentrons + +COPY notify-server/setup.py notify-server/setup.py +COPY notify-server/README.rst notify-server/README.rst +COPY notify-server/notify_server notify-server/notify_server + +COPY robot-server/setup.py robot-server/setup.py +COPY robot-server/robot_server robot-server/robot_server + +RUN cd shared-data/python && python3 setup.py bdist_wheel -d /dist/ +RUN cd api && python3 setup.py bdist_wheel -d /dist/ +RUN cd notify-server && python3 setup.py bdist_wheel -d /dist/ +RUN cd robot-server && python3 setup.py bdist_wheel -d /dist/ + +FROM base +COPY --from=builder /dist /dist +RUN pip install /dist/* \ No newline at end of file diff --git a/api/MANIFEST.in b/api/MANIFEST.in index 6cfcd94fa52..55b69639860 100755 --- a/api/MANIFEST.in +++ b/api/MANIFEST.in @@ -1,5 +1,4 @@ include src/opentrons/package.json graft src/opentrons/config graft src/opentrons/resources -include src/opentrons/server/openapi.json exclude pyproject.toml diff --git a/api/src/opentrons/hardware_control/controller.py b/api/src/opentrons/hardware_control/controller.py index 2ebd0914156..a28bfa6230c 100644 --- a/api/src/opentrons/hardware_control/controller.py +++ b/api/src/opentrons/hardware_control/controller.py @@ -269,17 +269,16 @@ def disengage_axes(self, axes: List[str]): self._smoothie_driver.disengage_axis(''.join(axes)) def set_lights(self, button: Optional[bool], rails: Optional[bool]): - if opentrons.config.IS_ROBOT: - if button is not None: - self.gpio_chardev.set_button_light(blue=button) - if rails is not None: - self.gpio_chardev.set_rail_lights(rails) + if button is not None: + self.gpio_chardev.set_button_light(blue=button) + if rails is not None: + self.gpio_chardev.set_rail_lights(rails) def get_lights(self) -> Dict[str, bool]: - if not opentrons.config.IS_ROBOT: - return {} - return {'button': self.gpio_chardev.get_button_light()[2], - 'rails': self.gpio_chardev.get_rail_lights()} + return { + 'button': self.gpio_chardev.get_button_light()[2], + 'rails': self.gpio_chardev.get_rail_lights() + } def pause(self): self._smoothie_driver.pause() diff --git a/api/src/opentrons/hardware_control/emulation/app.py b/api/src/opentrons/hardware_control/emulation/app.py index 5dbaac2c707..378a23bb0e0 100644 --- a/api/src/opentrons/hardware_control/emulation/app.py +++ b/api/src/opentrons/hardware_control/emulation/app.py @@ -28,7 +28,7 @@ async def run_server(host: str, port: int, handler: ConnectionHandler) -> None: async def run() -> None: """Run the module emulators.""" - host = "127.0.0.1" + host = "0.0.0.0" await asyncio.gather( run_server(host=host, diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000000..f7bdba9962f --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,27 @@ +version: '3' +services: + emulator: + build: . + command: python3 -m opentrons.hardware_control.emulation.app + ports: + - '9996:9996' + - '9997:9997' + - '9998:9998' + - '9999:9999' + robot-server: + build: . + command: uvicorn "robot_server:app" --host 0.0.0.0 --port 31950 --ws wsproto --reload + ports: + - '31950:31950' + environment: + - OT_API_CONFIG_DIR=/config + - OT_SMOOTHIE_EMULATOR_URI=socket://emulator:9996 + - OT_THERMOCYCLER_EMULATOR_URI=socket://emulator:9997 + - OT_TEMPERATURE_EMULATOR_URI=socket://emulator:9998 + - OT_MAGNETIC_EMULATOR_URI=socket://emulator:9999 + links: + - 'emulator' + depends_on: + - 'emulator' + volumes: + - .opentrons_config:/config:rw diff --git a/robot-server/setup.py b/robot-server/setup.py index 3279f7f9196..6a583284c93 100755 --- a/robot-server/setup.py +++ b/robot-server/setup.py @@ -52,7 +52,11 @@ def get_version(): INSTALL_REQUIRES = [ 'fastapi==0.54.1', 'python-multipart==0.0.5', + 'uvicorn==0.11.3', + 'python-dotenv', 'opentrons', + 'wsproto==0.15.0', + 'typing-extensions>=3.7.4.3', ]