Stage SMB CF/CFE inputs for Windows Agent
This commit is contained in:
@@ -44,6 +44,7 @@ async def html5_ai_structure_run(
|
||||
prepare: Callable[..., dict[str, Any]],
|
||||
work_root: Path,
|
||||
start_binary_job: Callable[..., Any] | None = None,
|
||||
stage_binary_input: Callable[..., Any] | None = None,
|
||||
save_run_state: Callable[[str, dict[str, Any]], None] | None = None,
|
||||
load_credentials: Callable[[str], SmbCredentials | None] | None = None,
|
||||
save_credentials: Callable[[str, SmbCredentials], None] | None = None,
|
||||
@@ -85,11 +86,26 @@ async def html5_ai_structure_run(
|
||||
if binary_match is not None:
|
||||
if start_binary_job is None or save_run_state is None:
|
||||
return render_html5_ai_structure_error("Сервис подготовки CF/CFE через Windows Agent не подключен.")
|
||||
binary_input_path = input_path
|
||||
if is_unc_path(input_path) and local_input.exists() and stage_binary_input is not None:
|
||||
try:
|
||||
binary_input_path = await stage_binary_input(
|
||||
project_id=project_id,
|
||||
effective_project_id=effective_project_id,
|
||||
local_input=local_input,
|
||||
username=username,
|
||||
password=password,
|
||||
domain=domain or None,
|
||||
)
|
||||
except HTTPException as error:
|
||||
return render_html5_ai_structure_error(str(error.detail))
|
||||
except RuntimeError as error:
|
||||
return render_html5_ai_structure_error(str(error))
|
||||
try:
|
||||
job = await start_binary_job(
|
||||
project_id=project_id,
|
||||
effective_project_id=effective_project_id,
|
||||
input_path=input_path,
|
||||
input_path=binary_input_path,
|
||||
detected_binary_relative_path=binary_match.get("relative_path"),
|
||||
detected_binary_relative_paths=binary_match.get("binary_relative_paths"),
|
||||
)
|
||||
|
||||
@@ -193,7 +193,7 @@ from api_server.snapshot_module_service import (
|
||||
module_sources_for_object as _snapshot_module_sources_for_object,
|
||||
snapshot_bsl_completion_items as _snapshot_bsl_completion_items,
|
||||
)
|
||||
from api_server.smb_paths import is_unc_path
|
||||
from api_server.smb_paths import copy_local_tree_to_smb, is_unc_path
|
||||
from api_server.time_utils import current_timestamp as _current_timestamp
|
||||
from impact_engine import object_impact, routine_impact
|
||||
from incremental_indexer import rebuild_changed_file
|
||||
@@ -657,6 +657,39 @@ async def _queue_ai_structure_agent_step(
|
||||
)
|
||||
|
||||
|
||||
async def _stage_ai_structure_binary_input_for_agent(
|
||||
*,
|
||||
project_id: str,
|
||||
effective_project_id: str,
|
||||
local_input: Path,
|
||||
username: str,
|
||||
password: str,
|
||||
domain: str | None = None,
|
||||
) -> str:
|
||||
settings = _project_settings_or_404(project_id)
|
||||
agent_id = _agent_id_for_source(settings, ImportSourceKind.CF_FILE)
|
||||
if not agent_id:
|
||||
raise HTTPException(status_code=400, detail="В настройках проекта не выбран Windows Agent для CF/CFE.")
|
||||
agent_status = _agent_status_with_liveness(_agent_statuses.get(agent_id, AgentStatus(agent_id=agent_id)))
|
||||
roots = [str(item).strip() for item in getattr(agent_status, "network_roots", []) if str(item).strip()]
|
||||
if not roots:
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail=f"У Windows Agent {agent_id} не настроены доступные сетевые корни для staging CF/CFE.",
|
||||
)
|
||||
if not local_input.exists():
|
||||
raise HTTPException(status_code=404, detail=f"Сервер не нашел локальную копию входных файлов: {local_input}")
|
||||
stage_root = ntpath.join(roots[0], "SFERA", "ai-structure-staging", f"{effective_project_id}-{uuid4().hex}")
|
||||
copy_local_tree_to_smb(
|
||||
source=local_input,
|
||||
target=stage_root,
|
||||
username=username,
|
||||
password=password,
|
||||
domain=domain or None,
|
||||
)
|
||||
return stage_root
|
||||
|
||||
|
||||
async def _start_ai_structure_agent_job(
|
||||
*,
|
||||
project_id: str,
|
||||
@@ -2117,6 +2150,7 @@ async def html5_project_ai_structure_run(project_id: str, request: Request) -> R
|
||||
prepare=_prepare_ai_structure,
|
||||
work_root=_storage.root / "ai_structure_work",
|
||||
start_binary_job=_start_ai_structure_agent_job,
|
||||
stage_binary_input=_stage_ai_structure_binary_input_for_agent,
|
||||
save_run_state=_save_ai_structure_agent_run,
|
||||
load_credentials=_load_ai_structure_smb_credentials,
|
||||
save_credentials=_save_ai_structure_smb_credentials,
|
||||
|
||||
@@ -2091,6 +2091,10 @@ def test_html5_ai_structure_routes_unc_directory_with_cf_through_windows_agent(m
|
||||
started.update(kwargs)
|
||||
return FakeJob()
|
||||
|
||||
async def fake_stage_binary_input(**kwargs):
|
||||
started["staged_from"] = kwargs["local_input"]
|
||||
return r"\\192.168.220.220\mst\SFERA\ai-structure-staging\unc-demo"
|
||||
|
||||
saved_runs: dict[str, dict[str, object]] = {}
|
||||
|
||||
monkeypatch.setattr(controller, "copy_smb_tree_to_local", fake_copy_smb_tree_to_local)
|
||||
@@ -2108,15 +2112,17 @@ def test_html5_ai_structure_routes_unc_directory_with_cf_through_windows_agent(m
|
||||
prepare=lambda **_: {},
|
||||
work_root=tmp_path / "work",
|
||||
start_binary_job=fake_start_binary_job,
|
||||
stage_binary_input=fake_stage_binary_input,
|
||||
save_run_state=lambda job_id, payload: saved_runs.setdefault(job_id, payload),
|
||||
)
|
||||
)
|
||||
|
||||
assert "Windows Agent" in html
|
||||
assert copied_targets
|
||||
assert started["input_path"] == r"\\192.168.220.200\mst\1c\MARKA\CODEX\CF"
|
||||
assert started["input_path"] == r"\\192.168.220.220\mst\SFERA\ai-structure-staging\unc-demo"
|
||||
assert started["detected_binary_relative_path"] == "base.cf"
|
||||
assert started["detected_binary_relative_paths"] == ["base.cf"]
|
||||
assert started["staged_from"] == copied_targets[0][1]
|
||||
assert "agent-import-test" in saved_runs
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user