Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

scenario_execution library for docker interaction #205

Merged
merged 33 commits into from
Oct 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
1a58734
initial scenario_execution lib for docker with docker run action
fmirus Oct 2, 2024
581f631
test update
fmirus Oct 2, 2024
4a9729a
additional arguments for docker run action
fmirus Oct 2, 2024
bd6a506
fix
fmirus Oct 7, 2024
fd5bc82
Merge remote-tracking branch 'origin/main' into docker_lib
fmirus Oct 7, 2024
6335d80
fix
fmirus Oct 7, 2024
b382bfa
add name argument to docker run action
fmirus Oct 7, 2024
6a4cd75
add docker exec action
fmirus Oct 7, 2024
478640d
add/update test scenarios
fmirus Oct 7, 2024
7ddb369
minor scenario update
fmirus Oct 7, 2024
3c8b880
cleanup
fmirus Oct 7, 2024
fa0e7f6
add network argument to docker run action
fmirus Oct 7, 2024
a70fe89
properly stop running container on scenario execution shutdown
fmirus Oct 7, 2024
b28f457
minor updates in docker_exec and docker_run actions
fmirus Oct 9, 2024
67d32c8
docker copy action
fmirus Oct 9, 2024
d7c302d
docker put action and scenario updates
fmirus Oct 10, 2024
da4c8d6
Merge branch 'main' into docker_lib
fmirus Oct 10, 2024
92f7368
docs
fmirus Oct 10, 2024
4879ede
scenario cleanup
fmirus Oct 10, 2024
58af2e8
update docker_exec action to fail if the given command fails
fmirus Oct 10, 2024
4a17efd
test update
fmirus Oct 10, 2024
564f4f9
add test for docker_exec
fmirus Oct 10, 2024
fa3ee0a
fix test for docker_exec
fmirus Oct 10, 2024
5963396
add test for docer copy and move all tests for scenario_execution_docker
fmirus Oct 10, 2024
cc55c34
test updates
fmirus Oct 10, 2024
3e52dea
test fix
fmirus Oct 10, 2024
4978206
add test for docker put
fmirus Oct 10, 2024
565cfe1
test updates
fmirus Oct 10, 2024
b4780f9
format fix
fmirus Oct 10, 2024
aaf3914
format fix
fmirus Oct 10, 2024
571fd34
minor doc update
fmirus Oct 11, 2024
9d6c153
set remove option to true as default
fmirus Oct 11, 2024
910a785
state machine updates in docker actions
fmirus Oct 11, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion docs/dictionary.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,6 @@ Kubernetes
yaml
absolutized
moveit
replan
replan
effector
mnt
161 changes: 160 additions & 1 deletion docs/libraries.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ Beside ``osc.standard`` provided by OpenSCENARIO 2 (which we divide into ``osc.s

* - Name
- Description
* - ``osc.docker``
- Docker Library (provided with :repo_link:`libs/scenario_execution_docker`)
* - ``osc.gazebo``
- Gazebo Library (provided with :repo_link:`libs/scenario_execution_gazebo`)
* - ``osc.helpers``
Expand All @@ -32,6 +34,163 @@ Beside ``osc.standard`` provided by OpenSCENARIO 2 (which we divide into ``osc.s
Additional features can be implemented by defining your own library.


Docker
------

The library contains actions to interact with `Docker <https://www.docker.com/>`_. Import it with ``import osc.docker``. It's provided by the package :repo_link:`libs/scenario_execution_docker`.

``docker_run()``
^^^^^^^^^^^^^^^^

Runs a Docker container

.. list-table::
:widths: 15 15 5 65
:header-rows: 1
:class: tight-table

* - Parameter
- Type
- Default
- Description
* - ``image``
- ``string``
-
- The image to run
* - ``command``
- ``string``
-
- The command to run in the container
* - ``container_name``
- ``string``
-
- The name for this container
* - ``detach``
- ``bool``
- false
- Whether to run container in the background
* - ``environment``
- ``list of string``
-
- Environment variables to set inside the container, i.e., a list of strings in the format ["SOMEVARIABLE=xxx"].
* - ``network``
- ``string``
-
- Name of the network this container will be connected to at creation time
* - ``privileged``
- ``bool``
- false
- Give extended privileges to this container
* - ``remove``
- ``bool``
- true
- Remove the container when it as finished running
* - ``stream``
- ``bool``
- true
- If true and detach is false, return a log generator instead of a string. Ignored if detach is true.
* - ``volumes``
- ``list of string``
-
- A list of strings which each one of its elements specifies a mount volume: ['/home/user1/:/mount/vol2','/home/user2/:/mount/vol1']

``docker_exec()``
^^^^^^^^^^^^^^^^^

Runs a command inside a given Docker container

.. list-table::
:widths: 15 15 5 65
:header-rows: 1
:class: tight-table

* - Parameter
- Type
- Default
- Description
* - ``container``
- ``string``
-
- The name or id of the container to run the command in
* - ``container``
- ``string``
-
- The name or id of the container to run the command in
* - ``command``
- ``string``
-
- The command to run inside the container
* - ``environment``
- ``list of string``
-
- Environment variables to set inside the container, i.e., a list of strings in the format ["SOMEVARIABLE=xxx"].
* - ``privileged``
- ``bool``
- false
- Give extended privileges to this container
* - ``user``
- ``string``
- root
- User to execute command as
* - ``workdir``
- ``string``
-
- Path to working directory for this exec session

``docker_copy()``
^^^^^^^^^^^^^^^^^

Copy a file or folder from the container.
Note that this actions potentially blocks other action calls if the copied content is large.
In case large files or folders need to be copied, consider mounting a volume to the container instead of this action.

.. list-table::
:widths: 15 15 5 65
:header-rows: 1
:class: tight-table

* - Parameter
- Type
- Default
- Description
* - ``container``
- ``string``
-
- The name or id of the container to run the command in
* - ``file_path``
- ``string``
-
- Path to the file or folder inside the container to retrieve

``docker_put()``
^^^^^^^^^^^^^^^^^

Copy a file or folder from the local system into a running container.
Note that this actions potentially blocks other action calls if the copied content is large.
In case large files or folders need to be copied, consider mounting a volume to the container instead of this action.

.. list-table::
:widths: 15 15 5 65
:header-rows: 1
:class: tight-table

* - Parameter
- Type
- Default
- Description
* - ``container``
- ``string``
-
- The name or id of the container to put the file or folder into
* - ``source_path``
- ``string``
-
- Path to the file or folder in the local system to copy
* - ``target_path``
- ``string``
-
- Target path inside the container to put the file or folder

Gazebo
------

Expand Down Expand Up @@ -1604,4 +1763,4 @@ Capture the screen content within a video.
* - ``frame_rate``
- ``float``
- ``25.0``
- Frame-rate of the resulting video
- Frame-rate of the resulting video
1 change: 1 addition & 0 deletions libs/scenario_execution_docker/MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
include scenario_execution_docker/lib_osc/*.osc
8 changes: 8 additions & 0 deletions libs/scenario_execution_docker/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Scenario Execution Library for Docker interaction

The `scenario_execution_docker` package provides actions to interact with docker.

It provides the following scenario execution library:

- `docker.osc`: Actions to interact with docker

23 changes: 23 additions & 0 deletions libs/scenario_execution_docker/package.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
<name>scenario_execution_docker</name>
<version>1.2.0</version>
<description>Scenario Execution library for docker interactions</description>
<author email="[email protected]">Intel Labs</author>
<maintainer email="[email protected]">Intel Labs</maintainer>
<license file="../../LICENSE">Apache-2.0</license>

<depend>scenario_execution</depend>

<exec_depend>python3-docker</exec_depend>

<test_depend>ament_copyright</test_depend>
<test_depend>ament_flake8</test_depend>
<test_depend>ament_pep257</test_depend>
<test_depend>python3-pytest</test_depend>

<export>
<build_type>ament_python</build_type>
</export>
</package>
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Copyright (C) 2024 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Copyright (C) 2024 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# Copyright (C) 2024 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0

from enum import Enum

import os
import docker
import tempfile
import tarfile
import py_trees
from scenario_execution.actions.base_action import BaseAction, ActionError


class CopyStatus(Enum):
IDLE = 1
FOUND_CONTAINER = 2
COPYING = 3
DONE = 4


class DockerCopy(BaseAction):
"""
Copy a file or folder from a running container
"""

def __init__(self, container: str, file_path: str):
super().__init__()
self.container = container
self.file_path = file_path

self.container_object = None
self.current_state = CopyStatus.IDLE
self.output_dir = None
self.client = None
self.result_data = None

def setup(self, **kwargs):
# create docker client
self.client = docker.from_env()

# check output_dir
if "output_dir" not in kwargs:
raise ActionError("output_dir not defined.", action=self)

if kwargs['output_dir']:
if not os.path.exists(kwargs['output_dir']):
raise ActionError(f"Specified destination dir '{kwargs['output_dir']}' does not exist", action=self)
self.output_dir = kwargs['output_dir']

def update(self) -> py_trees.common.Status:
if self.current_state == CopyStatus.IDLE:
try:
self.container_object = self.client.containers.get(self.container)
self.current_state = CopyStatus.FOUND_CONTAINER
except docker.errors.APIError as e:
self.feedback_message = f"Docker container {self.container} not yet running {e}" # pylint: disable= attribute-defined-outside-init
return py_trees.common.Status.RUNNING

if self.current_state == CopyStatus.FOUND_CONTAINER:
try:
self.result_data, _ = self.container_object.get_archive(
path=self.file_path)
self.current_state = CopyStatus.COPYING
self.feedback_message = f"Copying data from path {self.file_path} in container {self.container} to {self.output_dir}" # pylint: disable= attribute-defined-outside-init
except docker.errors.APIError as e:
self.feedback_message = f"Copying of data from path {self.file_path} failed: {e}" # pylint: disable= attribute-defined-outside-init
return py_trees.common.Status.FAILURE

if self.current_state == CopyStatus.COPYING:
output_tar = tempfile.NamedTemporaryFile(suffix=".tar")
try:
with open(output_tar.name, 'wb') as f:
for chunk in self.result_data:
f.write(chunk)
with tarfile.open(output_tar.name, 'r') as tar:
tar.extractall(self.output_dir)
self.current_state = CopyStatus.DONE
except tarfile.ReadError as e:
self.feedback_message = f"Copying of data from path {self.file_path} failed: {e}" # pylint: disable= attribute-defined-outside-init
return py_trees.common.Status.FAILURE

if self.current_state == CopyStatus.DONE:
self.feedback_message = f"Finished copying of data from path {self.file_path} to {self.output_dir}" # pylint: disable= attribute-defined-outside-init
return py_trees.common.Status.SUCCESS

return py_trees.common.Status.RUNNING
Loading