update: jupyter api payload, wire os.environ
This commit is contained in:
@@ -162,7 +162,7 @@ class RuntimeClient:
|
|||||||
logger.debug(ws)
|
logger.debug(ws)
|
||||||
body = {
|
body = {
|
||||||
"type": "notebook",
|
"type": "notebook",
|
||||||
"name": name,
|
"path": name,
|
||||||
"content": {
|
"content": {
|
||||||
"cells": cells if cells is not None else [],
|
"cells": cells if cells is not None else [],
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
@@ -199,7 +199,7 @@ class RuntimeClient:
|
|||||||
ws = await self._ensure_workspace(workspace_id)
|
ws = await self._ensure_workspace(workspace_id)
|
||||||
body = {
|
body = {
|
||||||
"type": "file",
|
"type": "file",
|
||||||
"name": name,
|
"path": name,
|
||||||
"content": content,
|
"content": content,
|
||||||
"format": "text",
|
"format": "text",
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ specific concerns:
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import os
|
||||||
import socket
|
import socket
|
||||||
import subprocess
|
import subprocess
|
||||||
import time
|
import time
|
||||||
@@ -30,6 +31,7 @@ def start_process(
|
|||||||
cmd: list[str],
|
cmd: list[str],
|
||||||
workspace_path: Path,
|
workspace_path: Path,
|
||||||
log_dir: str | Path = "/tmp/process_logs",
|
log_dir: str | Path = "/tmp/process_logs",
|
||||||
|
env: dict[str, str] | None = None,
|
||||||
) -> tuple[subprocess.Popen, Path]:
|
) -> tuple[subprocess.Popen, Path]:
|
||||||
"""Launch ``cmd`` as a subprocess and return ``(process, log_file)``.
|
"""Launch ``cmd`` as a subprocess and return ``(process, log_file)``.
|
||||||
|
|
||||||
@@ -44,6 +46,11 @@ def start_process(
|
|||||||
start_time = time.strftime("%Y%m%d_%H%M%S")
|
start_time = time.strftime("%Y%m%d_%H%M%S")
|
||||||
temp_log = log_dir_path / f"process_start_{start_time}.log"
|
temp_log = log_dir_path / f"process_start_{start_time}.log"
|
||||||
|
|
||||||
|
# 构建合并后的环境变量
|
||||||
|
full_env = os.environ.copy()
|
||||||
|
if env:
|
||||||
|
full_env.update(env)
|
||||||
|
|
||||||
with open(temp_log, "a", buffering=1) as log_file:
|
with open(temp_log, "a", buffering=1) as log_file:
|
||||||
process = subprocess.Popen(
|
process = subprocess.Popen(
|
||||||
cmd,
|
cmd,
|
||||||
@@ -51,6 +58,7 @@ def start_process(
|
|||||||
stdout=log_file,
|
stdout=log_file,
|
||||||
stderr=subprocess.STDOUT,
|
stderr=subprocess.STDOUT,
|
||||||
start_new_session=True,
|
start_new_session=True,
|
||||||
|
env=full_env,
|
||||||
)
|
)
|
||||||
|
|
||||||
final_log = log_dir_path / f"process_{process.pid}_{start_time}.log"
|
final_log = log_dir_path / f"process_{process.pid}_{start_time}.log"
|
||||||
|
|||||||
@@ -195,7 +195,8 @@ async def start_workspace(ws_id: str) -> dict:
|
|||||||
base_path = f"/jupyter/{ws_id}/"
|
base_path = f"/jupyter/{ws_id}/"
|
||||||
|
|
||||||
cmd = [
|
cmd = [
|
||||||
"jupyter", "notebook",
|
"jupyter",
|
||||||
|
"notebook",
|
||||||
f"--port={port}",
|
f"--port={port}",
|
||||||
"--ip=0.0.0.0",
|
"--ip=0.0.0.0",
|
||||||
"--no-browser",
|
"--no-browser",
|
||||||
@@ -212,12 +213,14 @@ async def start_workspace(ws_id: str) -> dict:
|
|||||||
]
|
]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
process, log_file = start_process(cmd, workspace_path.as_posix())
|
process, log_file = start_process(
|
||||||
|
cmd,
|
||||||
|
workspace_path.as_posix(),
|
||||||
|
env={"PATH": f"/app/.venv/bin:{os.environ.get('PATH', '')}"},
|
||||||
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Failed to start Jupyter for {ws_id}: {e}")
|
logger.error(f"Failed to start Jupyter for {ws_id}: {e}")
|
||||||
raise HTTPException(
|
raise HTTPException(status_code=500, detail=f"Failed to start Jupyter: {e}")
|
||||||
status_code=500, detail=f"Failed to start Jupyter: {e}"
|
|
||||||
)
|
|
||||||
|
|
||||||
full_url = f"{PUBLIC_BASE_URL}:{port}{base_path}?token={token}"
|
full_url = f"{PUBLIC_BASE_URL}:{port}{base_path}?token={token}"
|
||||||
meta_path = _meta_path(ws_id)
|
meta_path = _meta_path(ws_id)
|
||||||
@@ -341,8 +344,7 @@ async def get_workspace(ws_id: str) -> dict:
|
|||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=404,
|
status_code=404,
|
||||||
detail=(
|
detail=(
|
||||||
f"Jupyter process for workspace '{ws_id}' "
|
f"Jupyter process for workspace '{ws_id}' " "has terminated unexpectedly."
|
||||||
"has terminated unexpectedly."
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -416,7 +418,9 @@ def reconcile_processes() -> dict[str, int]:
|
|||||||
except PermissionError:
|
except PermissionError:
|
||||||
alive = True # someone else's process, leave alone
|
alive = True # someone else's process, leave alone
|
||||||
if not alive:
|
if not alive:
|
||||||
logger.info(f"reconcile: dropping stale sidecar for {entry} (pid {pid} dead)")
|
logger.info(
|
||||||
|
f"reconcile: dropping stale sidecar for {entry} (pid {pid} dead)"
|
||||||
|
)
|
||||||
_delete_meta(entry)
|
_delete_meta(entry)
|
||||||
counters["removed_meta"] += 1
|
counters["removed_meta"] += 1
|
||||||
return counters
|
return counters
|
||||||
|
|||||||
Reference in New Issue
Block a user