Files
wehub-resource-sync e0e362d700
SDK Tests / changes (push) Successful in 2m29s
Real E2E Tests / changes (push) Successful in 2m29s
Deploy Docs Pages / build (push) Has been cancelled
Deploy Docs Pages / deploy (push) Has been cancelled
Real E2E Tests / JavaScript E2E (docker bridge) (push) Has been cancelled
Real E2E Tests / Python E2E (docker bridge) (push) Has been cancelled
Real E2E Tests / Java E2E (docker bridge) (push) Has been cancelled
Real E2E Tests / C# E2E (docker bridge) (push) Has been cancelled
Real E2E Tests / Go E2E (docker bridge) (push) Has been cancelled
Real E2E Tests / Real E2E CI (push) Has been cancelled
SDK Tests / SDK CI (push) Has been cancelled
SDK Tests / CLI Tests (push) Has been cancelled
SDK Tests / Python SDK Quality (code-interpreter) (push) Has been cancelled
SDK Tests / Python SDK Quality (sandbox) (push) Has been cancelled
SDK Tests / Python SDK Tests (code-interpreter) (push) Has been cancelled
SDK Tests / JavaScript SDK Quality And Tests (code-interpreter) (push) Has been cancelled
SDK Tests / JavaScript SDK Quality And Tests (sandbox) (push) Has been cancelled
SDK Tests / Python SDK Tests (sandbox) (push) Has been cancelled
SDK Tests / CLI Quality (push) Has been cancelled
SDK Tests / Kotlin SDK Quality And Tests (sandbox) (push) Has been cancelled
SDK Tests / Kotlin SDK Quality And Tests (code-interpreter) (push) Has been cancelled
SDK Tests / C# SDK Quality And Tests (code-interpreter) (push) Has been cancelled
SDK Tests / C# SDK Quality And Tests (sandbox) (push) Has been cancelled
SDK Tests / Go SDK Quality And Tests (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:39:33 +08:00

318 lines
12 KiB
Python

# Copyright 2026 Alibaba Group Holding Ltd.
#
# 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.
"""
Windows-profile helpers specific to Docker sandbox provisioning.
Mixed into DockerSandboxService via DockerContainerOpsMixin.
"""
from __future__ import annotations
import io
import logging
import os
import tarfile
import time
from threading import Lock
from typing import Callable, Optional, TYPE_CHECKING
from uuid import uuid4
from docker.errors import DockerException
from fastapi import HTTPException, status
from opensandbox_server.services.constants import SandboxErrorCodes
from opensandbox_server.services.windows_common import is_windows_platform
if TYPE_CHECKING:
from opensandbox_server.api.schema import PlatformSpec
WINDOWS_REQUIRED_DEVICES = ("/dev/kvm", "/dev/net/tun")
WINDOWS_REQUIRED_CAP_ADD = ("NET_ADMIN", "NET_RAW")
WINDOWS_OEM_VOLUME_PREFIX = "opensandbox-win-oem"
def resolve_docker_platform(platform: Optional["PlatformSpec"]) -> Optional[str]:
"""Resolve Docker API ``platform`` argument for container create.
For windows profile (dockur/windows), the image itself is linux-based and
should not be forced to windows/* via Docker API platform pinning.
"""
if platform is None or is_windows_platform(platform):
return None
return f"{platform.os}/{platform.arch}"
def normalize_bootstrap_command(
bootstrap_command: list[str],
requested_windows_platform: bool,
) -> list[str]:
# For linux profile, normalize single-string command with spaces
# so bootstrap can exec reliably.
if requested_windows_platform:
return bootstrap_command
if len(bootstrap_command) != 1 or " " not in bootstrap_command[0]:
return bootstrap_command
import shlex
return shlex.split(bootstrap_command[0])
def validate_windows_runtime_prerequisites() -> None:
"""Validate host device paths required by dockur/windows runtime profile."""
missing = [device for device in WINDOWS_REQUIRED_DEVICES if not os.path.exists(device)]
if not missing:
return
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail={
"code": SandboxErrorCodes.INVALID_PARAMETER,
"message": (
"Windows profile requires host devices to be present: "
f"{', '.join(missing)}."
),
},
)
def apply_windows_runtime_host_config_defaults(
host_config_kwargs: dict,
sandbox_id: str,
) -> dict:
"""Apply runtime defaults required by Windows profile."""
updated = dict(host_config_kwargs)
default_binds = [f"{WINDOWS_OEM_VOLUME_PREFIX}-{sandbox_id}:/oem:rw"]
existing_binds = list(updated.get("binds") or [])
updated["binds"] = existing_binds + default_binds
existing_devices = list(updated.get("devices") or [])
existing_devices.extend(WINDOWS_REQUIRED_DEVICES)
updated["devices"] = existing_devices
required_caps = set(WINDOWS_REQUIRED_CAP_ADD)
cap_drop = [cap for cap in (updated.get("cap_drop") or []) if cap not in required_caps]
if cap_drop:
updated["cap_drop"] = cap_drop
else:
updated.pop("cap_drop", None)
cap_add = set(updated.get("cap_add") or [])
cap_add.update(WINDOWS_REQUIRED_CAP_ADD)
updated["cap_add"] = sorted(cap_add)
return updated
def fetch_execd_install_bat(
*,
docker_client,
execd_image: str,
cache: dict[str, bytes],
cache_lock: Lock,
docker_operation: Callable[[str, Optional[str]], object],
logger: logging.Logger,
) -> bytes:
"""Fetch install.bat from execd image and memoize in caller-provided cache."""
cached = cache.get("install_bat")
if cached is not None:
return cached
with cache_lock:
cached = cache.get("install_bat")
if cached is not None:
return cached
container = None
try:
with docker_operation("execd install.bat cache create container", "execd-cache"):
container = docker_client.containers.create(
image=execd_image,
command=["tail", "-f", "/dev/null"],
name=f"sandbox-execd-installbat-{uuid4()}",
)
with docker_operation("execd install.bat cache start container", "execd-cache"):
container.start()
with docker_operation("execd install.bat cache read archive", "execd-cache"):
stream, _ = container.get_archive("/install.bat")
tar_blob = b"".join(stream)
with tarfile.open(fileobj=io.BytesIO(tar_blob), mode="r:*") as tar:
member = next(
(m for m in tar.getmembers() if m.isfile() and m.name.endswith("install.bat")),
None,
)
if member is None:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail={
"code": SandboxErrorCodes.EXECD_DISTRIBUTION_FAILED,
"message": "install.bat was not found in execd image archive.",
},
)
extracted = tar.extractfile(member)
if extracted is None:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail={
"code": SandboxErrorCodes.EXECD_DISTRIBUTION_FAILED,
"message": "Failed to extract install.bat from execd image archive.",
},
)
data = extracted.read()
except HTTPException:
raise
except DockerException as exc:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail={
"code": SandboxErrorCodes.EXECD_DISTRIBUTION_FAILED,
"message": f"Failed to fetch install.bat from execd image: {str(exc)}",
},
) from exc
finally:
if container is not None:
try:
with docker_operation("execd install.bat cache cleanup container", "execd-cache"):
container.remove(force=True)
except DockerException as cleanup_exc:
logger.warning(
"Failed to cleanup temporary execd install.bat container: %s", cleanup_exc
)
cache["install_bat"] = data
return data
def fetch_execd_windows_binary(
*,
docker_client,
execd_image: str,
cache: dict[str, bytes],
cache_lock: Lock,
docker_operation: Callable[[str, Optional[str]], object],
logger: logging.Logger,
) -> bytes:
"""Fetch execd.exe from execd image and memoize in caller-provided cache."""
cached = cache.get("windows_execd_bin")
if cached is not None:
return cached
with cache_lock:
cached = cache.get("windows_execd_bin")
if cached is not None:
return cached
container = None
try:
with docker_operation("execd windows bin cache create container", "execd-cache"):
container = docker_client.containers.create(
image=execd_image,
command=["tail", "-f", "/dev/null"],
name=f"sandbox-execd-winbin-{uuid4()}",
)
with docker_operation("execd windows bin cache start container", "execd-cache"):
container.start()
with docker_operation("execd windows bin cache read archive", "execd-cache"):
stream, _ = container.get_archive("/execd.exe")
tar_blob = b"".join(stream)
with tarfile.open(fileobj=io.BytesIO(tar_blob), mode="r:*") as tar:
member = next(
(m for m in tar.getmembers() if m.isfile() and m.name.endswith("execd.exe")),
None,
)
if member is None:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail={
"code": SandboxErrorCodes.EXECD_DISTRIBUTION_FAILED,
"message": "execd.exe was not found in execd image archive.",
},
)
extracted = tar.extractfile(member)
if extracted is None:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail={
"code": SandboxErrorCodes.EXECD_DISTRIBUTION_FAILED,
"message": "Failed to extract execd.exe from execd image archive.",
},
)
data = extracted.read()
except HTTPException:
raise
except DockerException as exc:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail={
"code": SandboxErrorCodes.EXECD_DISTRIBUTION_FAILED,
"message": f"Failed to fetch execd.exe from execd image: {str(exc)}",
},
) from exc
finally:
if container is not None:
try:
with docker_operation(
"execd windows bin cache cleanup container", "execd-cache"
):
container.remove(force=True)
except DockerException as cleanup_exc:
logger.warning(
"Failed to cleanup temporary execd windows bin container: %s", cleanup_exc
)
cache["windows_execd_bin"] = data
return data
def install_windows_oem_scripts(
*,
container,
sandbox_id: str,
install_bat_bytes: bytes,
execd_windows_bin_bytes: bytes,
ensure_directory: Callable[[object, str, Optional[str]], None],
docker_operation: Callable[[str, Optional[str]], object],
) -> None:
"""Install OEM script for dockur/windows:
- C:\\OEM\\install.bat from execd image
"""
ensure_directory(container, "/oem", sandbox_id)
tar_stream = io.BytesIO()
with tarfile.open(fileobj=tar_stream, mode="w") as tar:
install_script = tarfile.TarInfo(name="oem/install.bat")
install_script.mode = 0o644
install_script.size = len(install_bat_bytes)
install_script.mtime = int(time.time())
tar.addfile(install_script, io.BytesIO(install_bat_bytes))
execd_bin = tarfile.TarInfo(name="oem/execd.exe")
execd_bin.mode = 0o644
execd_bin.size = len(execd_windows_bin_bytes)
execd_bin.mtime = int(time.time())
tar.addfile(execd_bin, io.BytesIO(execd_windows_bin_bytes))
tar_stream.seek(0)
try:
with docker_operation("install windows OEM scripts", sandbox_id):
container.put_archive(path="/", data=tar_stream.getvalue())
except DockerException as exc:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail={
"code": SandboxErrorCodes.BOOTSTRAP_INSTALL_FAILED,
"message": f"Failed to install windows OEM scripts: {str(exc)}",
},
) from exc