이 장은 PureCVisor Single Edge를 수정, 검증, 배포, 장애 분석하는 사람을 위한 작업 기준이다.
앞 장들이 기능 사용법을 설명한다면, 이 장은 변경을 안전하게 넣고 운영 상태를 해석하는 순서를 정의한다.
| 독자 | 이 장에서 얻어야 하는 것 |
|---|
| 신규 개발자 | 저장소 경계, 핵심 모듈, 먼저 읽을 문서, 최소 빌드/테스트 루틴 |
| 백엔드 엔지니어 | RPC 추가/변경, RBAC, fire-and-forget, audit, libvirt/ZFS/LXC 연동 규칙 |
| 프론트엔드 엔지니어 | Vanilla JS 모듈 구조, PCV.* 네임스페이스, EP 엔드포인트 레지스트리, sanitizer 규칙 |
| 운영/SRE | systemd, 로그, 헬스 체크, libvirt/ZFS/OVS 상태 확인, 장애 증거 수집 |
| 릴리스 담당 | Single Edge 공개 범위, 검증 명령, 문서/배포 산출물 동기화 |
| 상황 | 먼저 볼 장 | 다음 확인 |
|---|
| 처음 빌드한다 | 2장 설치 및 환경 구성 | 21장 아키텍처 리팩토링, 22장 품질 게이트 |
| VM 기능을 바꾼다 | 3장 VM 관리 | ADR-0022, ADR-0023, tests/test_vm_clone_plan.c |
| LXC 저장소를 바꾼다 | 4장 컨테이너 관리 | ADR-0058, src/modules/lxc/lxc_storage.c, make check-lxc-storage |
| REST/API를 바꾼다 | 14장 REST API | src/api/rest_server.c, src/api/dispatcher.c, scripts/verify_api_consistency.sh |
| 권한을 바꾼다 | 10장 보안 | make check-rbac, docs/adr/0019-rbac-uds-bypass-policy.md |
| Web UI를 바꾼다 | 13장 Web UI | ui/modules/endpoints.js, scripts/bundle-ui.sh, node --check ui/app.bundle.js, 공개 URL route smoke |
| 배포 전 검증한다 | 22장 품질 게이트 | make single, make test, make check-rbac, PCV_NO_DEPLOY=1 scripts/bundle-ui.sh |
- 현재 저장소는 Linux/KVM 기반 Single Edge 범위만 다룬다.
- 설계 결정은
docs/ADR_INDEX.md와 docs/adr/를 우선한다.
기존 구현을 바꾸면 관련 ADR 적용 상태를 먼저 확인한다.
- 장시간 RPC는 먼저
accepted 응답을 반환하고 GTask worker에서 실행한다.
닫힌 소켓으로 후속 응답을 보내는 패턴은 금지한다.
- fire-and-forget RPC는 dispatcher 자동 audit에 의존하지 않는다.
worker callback에서 실제 성공/실패 기준으로 pcv_audit_log()와 WebSocket job completion을 남긴다.
- destructive RPC는 가능하면 멱등성을 유지한다.
실패 경로는 생성된 dataset/file/domain을 best-effort로 정리해야 한다.
system()과 popen()은 사용하지 않는다.
외부 명령은 pcv_spawn_sync() 또는 pcv_spawn_pipe_sync()에 argv 배열로 넘긴다.
- VM/템플릿 이름은 핸들러 진입점에서 검증 함수를 거친다.
- UI 모듈은
PCV.* 네임스페이스와 ui/modules/endpoints.js의 EP 레지스트리를 사용한다.
innerHTML 대입은 sanitizer 또는 escape helper를 거친다.
- 관련 문서와 ADR을 먼저 읽는다.
- 변경 대상 모듈의 기존 호출 흐름을
rg로 추적한다.
- API/RPC/권한/비동기 여부를 먼저 결정한다.
- 구현은 기존 모듈 경계 안에서 최소 범위로 넣는다.
- 실패 경로와 audit/job completion을 성공 경로와 같은 수준으로 구현한다.
- UI가 필요하면
EP에 엔드포인트를 등록하고 unwrapData() / unwrapList() 패턴으로 응답을 처리한다.
- 영향 범위에 맞는 테스트와 정적 게이트를 실행한다.
docs/GUIDE.md, ui/guide-content.md, ADR, 검증 정책 중 바뀐 계약을 반영한다.
| 변경 유형 | 최소 검증 |
|---|
| C 코어/dispatcher | make single, make test, make check-rbac |
| fire-and-forget RPC | scripts/check_audit_placement.py, 관련 worker 성공/실패 audit 확인 |
| VM clone | ./test_runner -r /vm_clone_plan, scripts/check_vm_clone_cleanup.py, ADR-0023 실환경 기준 확인 |
| Web UI | PCV_NO_DEPLOY=1 scripts/bundle-ui.sh, python3 scripts/check_ui_bundle_fresh.py, node --check ui/app.bundle.js, 공개 URL 해시와 /ui#ops-triage 확인 |
| REST surface | scripts/verify_api_consistency.sh, 인증/권한/에러 응답 확인 |
| ZFS inflight/metric | ZFS inflight 정적 검사와 Web UI 모니터링 노출 검사 |
| 문서만 변경 | git diff --check, 공개 가이드 배포 시 /ui/guide-content.md 해시 확인 |
| 증상 | 확인 순서 |
|---|
| API가 실패한다 | /api/v1/health, journal, REST status/error body, dispatcher method 등록 |
| VM action이 거부된다 | JWT subject, RBAC role, VM owner metadata, make check-rbac 계약 |
| VM clone이 실패한다 | source VM shut off, disk 개수/type, libguestfs-tools, accepted 응답의 source_disk/target_disk, audit result |
| UI만 최신이 아니다 | 로컬 번들 해시, /usr/local/share/purecvisor/ui, 공개 URL 해시, Service Worker cache name, /ui base href, #/page 해시 라우팅 |
| 네트워크가 이상하다 | ip -brief addr, ovs-vsctl show, bridge metadata, nftables, dnsmasq 상태 |
| 스토리지 오류가 난다 | zpool status, zfs list -o name,origin, dataset lock, target cleanup 여부 |
변경 완료 보고에는 다음을 남긴다.
- 무엇을 바꿨는지: 사용자 관점의 동작 변화
- 어디를 바꿨는지: 주요 파일과 모듈
- 어떻게 검증했는지: 명령, 결과, 실환경 여부
- 남은 리스크: 실행하지 못한 테스트, 운영 권한/환경 제약
- 배포 여부: 로컬만 변경인지, 운영 서버와 공개 URL까지 반영했는지