Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
31 changes: 12 additions & 19 deletions .github/workflows/real-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ jobs:
runs-on: self-hosted
env:
UV_BIN: /home/admin/.local/bin
JAVA_VERSION: "17.0.14+7"
steps:
- name: Checkout code
uses: actions/checkout@v6
Expand All @@ -102,24 +101,17 @@ jobs:
uv --version
uv run python --version

- name: Set up JDK
run: |
# Adoptium Temurin JDK 17 for Linux x64
JAVA_MAJOR="${JAVA_VERSION%%.*}"
JAVA_URL_VERSION=$(echo "${JAVA_VERSION}" | sed 's/+/%2B/')
JAVA_DIR="/home/admin/.local/jdk-${JAVA_VERSION}"
if [ -x "${JAVA_DIR}/bin/java" ]; then
echo "JDK ${JAVA_VERSION} already cached"
else
echo "Downloading Temurin JDK ${JAVA_VERSION}..."
mkdir -p /home/admin/.local
curl -fsSL "https://api.adoptium.net/v3/binary/version/jdk-${JAVA_URL_VERSION}/linux/x64/jdk/hotspot/normal/eclipse?project=jdk" \
| tar -xzf - -C /home/admin/.local/
fi
echo "${JAVA_DIR}/bin" >> "$GITHUB_PATH"
echo "JAVA_HOME=${JAVA_DIR}" >> "$GITHUB_ENV"
export PATH="${JAVA_DIR}/bin:${PATH}"
java -version
- name: Set up JDK 8
uses: actions/setup-java@v5
with:
distribution: temurin
java-version: "8"

- name: Set up JDK 17
uses: actions/setup-java@v5
with:
distribution: temurin
java-version: "17"

- name: Clean up previous E2E resources
run: |
Expand All @@ -131,6 +123,7 @@ jobs:
GRADLE_USER_HOME: ${{ github.workspace }}/.gradle-user-home
run: |
set -e
export GRADLE_OPTS="-Dorg.gradle.java.installations.auto-detect=true -Dorg.gradle.java.installations.auto-download=false -Dorg.gradle.java.installations.paths=${JAVA_HOME_8_X64},${JAVA_HOME_17_X64}"

# Create config file
cat <<EOF > ~/.sandbox.toml
Expand Down
1 change: 1 addition & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Examples for common OpenSandbox use cases. Each subdirectory contains runnable c
- <img src="https://kubernetes.io/icons/favicon-32.png" alt="Kubernetes" width="16" height="16" style="display:inline-block;width:16px;height:16px;vertical-align:middle;margin-right:4px;" /> [**agent-sandbox**](agent-sandbox): Create a kubernetes-sigs/agent-sandbox instance and run a command
- 🧪 [**code-interpreter**](code-interpreter): Code Interpreter SDK singleton example
- 💾 [**host-volume-mount**](host-volume-mount): Mount host directories into sandboxes (read-write, read-only, subpath)
- ☁️ [**docker-ossfs-volume-mount**](docker-ossfs-volume-mount): Mount OSSFS volumes in Docker runtime (inline credentials, subpath, sharing)
- 🎯 [**rl-training**](rl-training): Reinforcement learning training loop inside a sandbox
- <img src="https://img.shields.io/badge/-%20-D97757?logo=claude&logoColor=white&style=flat-square" alt="Claude" width="16" height="16" style="display:inline-block;width:16px;height:16px;vertical-align:middle;margin-right:4px;" /> [**claude-code**](claude-code): Call Claude (Anthropic) API/CLI within the sandbox
- <img src="https://cli.iflow.cn/img/favicon.ico" alt="iFlow" width="16" height="16" style="display:inline-block;width:16px;height:16px;vertical-align:middle;margin-right:4px;" /> [**iflow-cli**](iflow-cli): CLI invocation template for iFlow/custom HTTP LLM services
Expand Down
112 changes: 112 additions & 0 deletions examples/docker-ossfs-volume-mount/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# Docker OSSFS Volume Mount Example

This example demonstrates how to use the new SDK `ossfs` volume model to mount Alibaba Cloud OSS into sandboxes on Docker runtime.

## What this example covers

1. **Basic read-write mount** on an OSSFS backend.
2. **Cross-sandbox sharing** on the same OSSFS backend path.
3. **Two mounts, different OSS prefixes via `subPath`**.

## Prerequisites

### 1) Start OpenSandbox server (Docker runtime)

Make sure your server host has:

- Linux host OS (OSSFS backend is not supported when OpenSandbox Server runs on Windows)
- `ossfs` installed
- FUSE support enabled
- writable local mount root for OSSFS (default `storage.ossfs_mount_root=/mnt/ossfs`)

`storage.ossfs_mount_root` is **optional** if you use the default `/mnt/ossfs`.
Even with on-demand mounting, the runtime still needs a deterministic host-side
base directory to place dynamic mounts (`<mount_root>/<bucket>/<subPath?>`).

Optional config example:

```toml
[runtime]
type = "docker"

[storage]
ossfs_mount_root = "/mnt/ossfs"
```

Then start the server:

```bash
opensandbox-server
```

### 2) Install Python SDK

```bash
uv pip install opensandbox
```

If your PyPI version does not include OSSFS volume models yet, install from source:

```bash
pip install -e sdks/sandbox/python
```

### 3) Prepare OSS credentials and target path

```bash
export SANDBOX_DOMAIN=localhost:8080
export SANDBOX_API_KEY=your-api-key
export SANDBOX_IMAGE=ubuntu

export OSS_BUCKET=your-bucket
export OSS_ENDPOINT=oss-cn-hangzhou.aliyuncs.com
export OSS_ACCESS_KEY_ID=your-ak
export OSS_ACCESS_KEY_SECRET=your-sk
```

## Run

```bash
uv run python examples/docker-ossfs-volume-mount/main.py
```

## Minimal SDK usage snippet

```python
from opensandbox import Sandbox
from opensandbox.models.sandboxes import OSSFS, Volume

sandbox = await Sandbox.create(
image="ubuntu",
volumes=[
Volume(
name="oss-data",
ossfs=OSSFS(
bucket="your-bucket",
endpoint="oss-cn-hangzhou.aliyuncs.com",
# version="2.0", # optional, default is "2.0"
accessKeyId="your-ak",
accessKeySecret="your-sk",
),
mountPath="/mnt/data",
subPath="train", # optional
readOnly=False, # optional
)
],
)
```

## Notes

- Current implementation supports **inline credentials only** (`accessKeyId`/`accessKeySecret`).
- Mounting is **on-demand** in Docker runtime (mount-or-reuse), not pre-mounted for all buckets.
- `ossfs.version` exists in API/SDK with enum `"1.0" | "2.0"`, and defaults to `"2.0"` when omitted.
- Docker runtime now applies **version-specific mount argument encoding**:
- `1.0`: mounts via `ossfs ... -o <option>`.
- `2.0`: mounts via `ossfs2 mount ... -c <config-file>` where options are written as `--<option>` config lines.
- `options` values must be **raw payloads** without leading `-` (for example: `allow_other`, `umask=0022`).

## References

- [OSEP-0003: Volume and VolumeBinding Support](../../oseps/0003-volume-and-volumebinding-support.md)
- [Sandbox Lifecycle API Spec](../../specs/sandbox-lifecycle.yml)
112 changes: 112 additions & 0 deletions examples/docker-ossfs-volume-mount/README_zh.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# Docker OSSFS 挂载示例

本示例演示如何使用新版 SDK 的 `ossfs` volume 模型,在 Docker 运行时将阿里云 OSS 挂载到沙箱容器。

## 覆盖场景

1. **基础读写挂载**(OSSFS backend)。
2. **跨沙箱共享数据**(同一 OSSFS backend path)。
3. **通过 `subPath` 挂载不同 OSS prefix**。

## 前置条件

### 1) 启动 OpenSandbox 服务(Docker runtime)

请确保服务端主机满足:

- Linux 主机系统(OpenSandbox Server 运行在 Windows 时不支持 OSSFS backend)
- 已安装 `ossfs`
- 已启用 FUSE
- 已有可写的 OSSFS 本地挂载根目录(默认 `storage.ossfs_mount_root=/mnt/ossfs`)

`storage.ossfs_mount_root` 是**可选配置**(使用默认值时可不写)。
即使是按需动态挂载,运行时仍需要一个确定的宿主机根目录来放置挂载点:
`<mount_root>/<bucket>/<subPath?>`。

可选配置示例:

```toml
[runtime]
type = "docker"

[storage]
ossfs_mount_root = "/mnt/ossfs"
```

启动服务:

```bash
opensandbox-server
```

### 2) 安装 Python SDK

```bash
uv pip install opensandbox
```

如果当前 PyPI 版本还不包含 OSSFS 相关模型,可从源码安装:

```bash
pip install -e sdks/sandbox/python
```

### 3) 配置 OSS 参数

```bash
export SANDBOX_DOMAIN=localhost:8080
export SANDBOX_API_KEY=your-api-key
export SANDBOX_IMAGE=ubuntu

export OSS_BUCKET=your-bucket
export OSS_ENDPOINT=oss-cn-hangzhou.aliyuncs.com
export OSS_ACCESS_KEY_ID=your-ak
export OSS_ACCESS_KEY_SECRET=your-sk
```

## 运行

```bash
uv run python examples/docker-ossfs-volume-mount/main.py
```

## SDK 最小示例

```python
from opensandbox import Sandbox
from opensandbox.models.sandboxes import OSSFS, Volume

sandbox = await Sandbox.create(
image="ubuntu",
volumes=[
Volume(
name="oss-data",
ossfs=OSSFS(
bucket="your-bucket",
endpoint="oss-cn-hangzhou.aliyuncs.com",
# version="2.0", # 可选,默认 "2.0"
accessKeyId="your-ak",
accessKeySecret="your-sk",
),
mountPath="/mnt/data",
subPath="train", # 可选
readOnly=False, # 可选
)
],
)
```

## 说明

- 当前实现仅支持**内联凭据**(`accessKeyId` / `accessKeySecret`)。
- Docker 运行时采用**按需挂载**(mount-or-reuse),不是预挂载所有 bucket。
- API/SDK 中 `ossfs.version` 字段存在,枚举为 `"1.0"` / `"2.0"`,省略时默认 `"2.0"`。
- Docker 运行时已按 `version` 区分挂载参数编码:
- `1.0`:通过 `ossfs ... -o <option>` 挂载。
- `2.0`:通过 `ossfs2 mount ... -c <config-file>` 挂载,`options` 以 `--<option>` 配置项写入配置文件。
- `options` 必须是**不带前缀 `-` 的原始参数值**(例如:`allow_other`、`umask=0022`)。

## 参考

- [OSEP-0003: Volume 与 VolumeBinding 支持](../../oseps/0003-volume-and-volumebinding-support.md)
- [Sandbox Lifecycle API 规范](../../specs/sandbox-lifecycle.yml)
Loading