배경
하나의 Storage Service 백킹 볼륨 안에 계층형 디렉터리를 구성하고, 부모 디렉터리와 특정 하위 디렉터리를 각각 독립된 NFS export 또는 SMB share로 노출해야 하는 운영 요구가 있다.
예시:
- 부모 데이터 경로:
/export/share
- 하위 데이터 경로:
/export/share/project-a
- NFS 클라이언트 경로:
/share, /project-a
- SMB 공유 이름:
share, project-a
현재 구현은 NFS와 SMB 모두 /export/<이름> 형태의 직접 자식 경로만 허용하므로, /export/share/project-a와 같은 하위 디렉터리를 별도 export/share로 생성할 수 없다.
확인된 AS-IS
API 및 서비스 계층
StorageServiceManagerImpl.validateNfsExportPath()는 /export/<name>과 정확히 일치하고 깊이가 1인 경로만 허용한다.
StorageServiceManagerImpl.validateSmbSharePath()도 동일하게 /export/<name> 직접 자식만 허용한다.
- NFS create/update API에는
relativepath가 선언되어 있지만, 현재 생성·수정 흐름에서 실제 백킹 경로 계산에 연결되지 않는다.
- SMB create/update API에는 백킹 볼륨 상대 경로를 지정하는 대응 파라미터가 없다.
- 공통 경로 충돌 검증은 동일 볼륨의 부모·자식 관계를 표현할 여지가 있으나, 프로토콜별 직접 자식 검증에서 먼저 차단된다.
SystemVM 런타임
ablestack-storagectl은 relativeSharePath를 볼륨 마운트 경로 아래의 실제 백킹 경로로 해석할 수 있다.
- NFS-Ganesha는 물리
Path와 클라이언트 노출 Pseudo를 별도로 렌더링한다.
- Samba 공유도 공유 이름과 실제
path를 별도로 렌더링할 수 있다.
따라서 런타임 기반은 존재하며, API·서비스·검증·UI의 경로 모델을 일관되게 연결하는 개선이 필요하다.
TO-BE 경로 모델
공유의 물리 위치를 다음 키로 식별한다.
Storage Service instance ID + backing volume ID + normalized volume-relative path
volumeRelativePath: 선택한 백킹 볼륨 루트 기준 상대 경로
backingPath: SystemVM에서 계산한 실제 경로. 외부 입력값으로 신뢰하지 않는다.
- NFS
path/pseudo: 클라이언트에 노출할 NFS 루트
- SMB
name: 클라이언트에 노출할 SMB 공유 이름
기존 /export/<name> 직접 자식 생성은 기본 동작으로 유지한다. 중첩 공유는 사용자가 백킹 볼륨 상대 경로를 명시한 경우에만 활성화한다.
검증 및 데이터 안전 규칙
- 부모·자식 공유는 같은 Storage Service 인스턴스와 같은 백킹 볼륨에서만 허용한다.
- 정규화 후 동일한 물리 경로의 중복 공유는 차단한다. 단, 명시적인 NFS/SMB 교차 프로토콜 경로 공유 정책은 기존 규칙을 유지한다.
- 절대 경로, 빈 경로,
./.., 심볼릭 링크를 통한 볼륨 밖 이탈을 차단한다.
realpath 결과가 선택된 볼륨 마운트 루트 아래인지 확인한다.
- 부모와 자식 사이에 별도 파일시스템 마운트가 있으면 차단한다.
findmnt/stat로 마운트 소스와 장치 경계를 확인한다.
- 디렉터리 자동 생성은 선택된 볼륨 루트 아래에서만 수행한다.
- 자식 공유 삭제는 export/share 설정만 제거하며 데이터 디렉터리는 삭제하지 않는다.
- 자식 공유가 존재하는 부모 공유 삭제는 차단하거나 영향 범위를 명시한 최종 확인 절차를 요구한다.
- 해당 볼륨을 사용하는 부모 또는 자식 공유가 하나라도 있으면 볼륨 연결 해제를 비활성화한다.
- POSIX 소유권·권한 변경은 기본적으로 선택 경로에만 적용하고 재귀 적용은 명시적 선택으로 유지한다. 교차 프로토콜 POSIX 정책은 #903과 일관성을 유지한다.
API 및 백엔드 변경
NFS
CreateStorageNfsExportCmd와 UpdateStorageNfsExportCmd의 relativepath를 실제 생성·수정 로직에 연결한다.
resolveFileShareBackingPath() 및 desired-state config의 relativeSharePath에 정규화된 값을 전달한다.
- NFS 노출 경로와 물리 백킹 경로를 분리해 저장·응답한다.
SMB
- SMB share create/update API에 NFS와 동일 의미의
relativepath를 추가한다.
- share 이름과 물리 백킹 경로를 분리해 저장·응답한다.
공통
- 응답에
volumeid, volumerelativepath, 계산된 backingpath, 부모 공유 관계를 포함한다.
- 부모 관계는 동일 볼륨의 정규화된 경로로 계산하며, UI 및 감사 용도의
parentshareid를 추가할 경우에도 계산 결과를 최종 기준으로 사용한다.
- desired-state 적용 실패 시 DB와 생성된 볼륨·디렉터리의 정리 정책을 기존 원자적 생성 규칙과 맞춘다.
- 기존 직접 자식 경로 데이터에 대한 호환성을 유지한다.
SystemVM 변경
- 적용 전에
realpath, stat, findmnt 기반 preflight를 수행한다.
- NFS-Ganesha는 중첩된 실제 백킹 경로를
Path로 사용하고, 클라이언트 루트는 고유한 Pseudo로 유지한다.
- Samba는 고유한 공유 이름을 중첩된 실제 백킹 경로에 매핑한다.
- inventory/readback에 볼륨 ID, 볼륨 상대 경로, 실제 백킹 경로를 함께 반환한다.
- reconcile 및 재부팅 복구 시 부모·자식 공유의 적용 순서와 무관하게 동일한 설정을 복원한다.
UI 변경
- NFS export 및 SMB share 생성·수정 모달에
백킹 볼륨 상대 경로 입력 항목을 추가한다.
- 선택한 볼륨 기준의 예상 실제 경로와 클라이언트 노출 경로를 구분하여 표시한다.
- 동일 볼륨의 기존 경로를 트리 또는 경로 목록으로 제공해 부모·자식 관계를 확인할 수 있게 한다.
- 부모 공유 데이터가 자식 공유를 통해서도 보일 수 있음을 안내하고, ACL은 각 export/share 단위로 독립 적용됨을 명시한다.
- 잘못된 경로, 다른 볼륨과의 중첩, 경로 이탈을 제출 전에 검증한다.
- 중첩 공유는 같은 백킹 볼륨 용량을 공유하므로 별도 전용 용량처럼 표시하지 않는다.
- 기존 세로형 모달, 단일 내부 스크롤, 라이트/다크 테마 규칙을 유지한다.
테스트 항목
완료 조건
- NFS와 SMB 모두 같은 백킹 볼륨의 하위 디렉터리를 독립된 export/share로 생성·수정·삭제할 수 있다.
- 물리 백킹 경로와 클라이언트 노출 경로가 API, DB, SystemVM, UI에서 일관되게 표시된다.
- 경로 이탈, 교차 볼륨 중첩, 부모 삭제, 볼륨 연결 해제에 대한 데이터 안전 검증이 적용된다.
- 기존 직접 자식 경로 및 NFS/SMB 교차 프로토콜 공유 동작에 회귀가 없다.
추적
배경
하나의 Storage Service 백킹 볼륨 안에 계층형 디렉터리를 구성하고, 부모 디렉터리와 특정 하위 디렉터리를 각각 독립된 NFS export 또는 SMB share로 노출해야 하는 운영 요구가 있다.
예시:
/export/share/export/share/project-a/share,/project-ashare,project-a현재 구현은 NFS와 SMB 모두
/export/<이름>형태의 직접 자식 경로만 허용하므로,/export/share/project-a와 같은 하위 디렉터리를 별도 export/share로 생성할 수 없다.확인된 AS-IS
API 및 서비스 계층
StorageServiceManagerImpl.validateNfsExportPath()는/export/<name>과 정확히 일치하고 깊이가 1인 경로만 허용한다.StorageServiceManagerImpl.validateSmbSharePath()도 동일하게/export/<name>직접 자식만 허용한다.relativepath가 선언되어 있지만, 현재 생성·수정 흐름에서 실제 백킹 경로 계산에 연결되지 않는다.SystemVM 런타임
ablestack-storagectl은relativeSharePath를 볼륨 마운트 경로 아래의 실제 백킹 경로로 해석할 수 있다.Path와 클라이언트 노출Pseudo를 별도로 렌더링한다.path를 별도로 렌더링할 수 있다.따라서 런타임 기반은 존재하며, API·서비스·검증·UI의 경로 모델을 일관되게 연결하는 개선이 필요하다.
TO-BE 경로 모델
공유의 물리 위치를 다음 키로 식별한다.
Storage Service instance ID + backing volume ID + normalized volume-relative pathvolumeRelativePath: 선택한 백킹 볼륨 루트 기준 상대 경로backingPath: SystemVM에서 계산한 실제 경로. 외부 입력값으로 신뢰하지 않는다.path/pseudo: 클라이언트에 노출할 NFS 루트name: 클라이언트에 노출할 SMB 공유 이름기존
/export/<name>직접 자식 생성은 기본 동작으로 유지한다. 중첩 공유는 사용자가 백킹 볼륨 상대 경로를 명시한 경우에만 활성화한다.검증 및 데이터 안전 규칙
./.., 심볼릭 링크를 통한 볼륨 밖 이탈을 차단한다.realpath결과가 선택된 볼륨 마운트 루트 아래인지 확인한다.findmnt/stat로 마운트 소스와 장치 경계를 확인한다.API 및 백엔드 변경
NFS
CreateStorageNfsExportCmd와UpdateStorageNfsExportCmd의relativepath를 실제 생성·수정 로직에 연결한다.resolveFileShareBackingPath()및 desired-state config의relativeSharePath에 정규화된 값을 전달한다.SMB
relativepath를 추가한다.공통
volumeid,volumerelativepath, 계산된backingpath, 부모 공유 관계를 포함한다.parentshareid를 추가할 경우에도 계산 결과를 최종 기준으로 사용한다.SystemVM 변경
realpath,stat,findmnt기반 preflight를 수행한다.Path로 사용하고, 클라이언트 루트는 고유한Pseudo로 유지한다.UI 변경
백킹 볼륨 상대 경로입력 항목을 추가한다.테스트 항목
.., 절대 경로, 심볼릭 링크, 별도 마운트를 통한 경로 이탈 차단/export/<name>직접 자식 생성·수정·삭제 회귀 테스트완료 조건
추적