cmlutil project export/import 를 실제로 돌리면서 만난 오류를 원인과 조치 순으로 정리한다. 설치와 기본 절차는 cmlutils 폐쇄망 설치와 CML 프로젝트 마이그레이션 을 본다.
export 전 검증에서 대상 프로젝트에 rsync 가능한 런타임이 붙어 있는지 검사한다. 카탈로그에 이미지가 있어도 프로젝트 레벨에 추가돼 있지 않으면 실패한다. 폐쇄망에서는 docker save → 반입 → docker load → 내부 레지스트리 경로로 docker tag/docker push 한 뒤 Site Administration → Runtime Catalog 에 등록하고, 프로젝트 Settings → Runtime 에서 그 런타임을 추가한다. latest 태그는 피하고 실제 태그를 쓴다. 레지스트리에는 UI 업로드가 아니라 push 로 올린다.
SSH connection successfull 뒤에 Got non zero return code. Retrying... 3회 후 실패하는 패턴이다. 타깃 세션의 authorized_keys 에 등록된 키가 bastion 이 쓰는 키(보통 ~/.ssh/id_rsa)와 다를 때 나타난다. 타깃 워크벤치의 해당 사용자 User Settings → Remote Editing → SSH public keys 에 export 때 성공한 bastion 공개키를 등록한 뒤 다시 import 한다. 세션 로그의 Authorized keys ak = [...] 항목과 ssh-keygen -lf ~/.ssh/*.pub 지문을 대조하면 확정된다.
config 의 username 은 접속 계정이 아니라 export 대상 프로젝트의 소유자 여야 한다. API 는 scope=all 로 목록을 돌려주지만 도구는 설정된 username 이 소유한 프로젝트 중에서만 이름을 찾는다. [DEFAULT] 나 프로젝트 섹션의 username 을 실제 owner 로 바꾼다. import 쪽에서는 이 username 이 곧 타깃 프로젝트의 owner 가 된다. 프로젝트마다 다른 owner 로 올리려면 섹션별로 그 사용자의 apiv1 키가 각각 필요하다.
타깃 API 는 프로젝트 이름에 영문자가 최소 한 글자 있어야 한다. 한글_프로젝트_01 처럼 한글·숫자·언더스코어만 있는 이름은 import 시 400 으로 거부된다. 인코딩 문제가 아니다. 조치는 export 산출물의 project-metadata 안 name 을 영문 접미사가 포함된 이름(한글_프로젝트_01_kb)으로 바꾸고, 폴더명·-p 값·config 섹션명을 모두 그 새 이름으로 통일하는 것이다. 근본적으로는 소스에서부터 영문자를 포함한 프로젝트명을 쓰는 정책이 낫다. 한글 이름은 slug 가 _ 하나로 축약되므로 한글 프로젝트가 여럿이면 slug 충돌 가능성도 있다.
import 는 성공(✔ Import of Project ... Successful)했는데 뒤이은 verify 단계에서 나는 오류다. 데이터 유실이 아니다. 검증 로직이 -p 값으로 config 섹션을 다시 읽는데 섹션명이 다르거나(위의 이름 변경 케이스), export-config 와 import-config 양쪽 중 한쪽에 섹션이 없을 때 발생한다. 섹션을 맞춘 뒤 cmlutil project validate-migration -p "<이름>" 만 다시 돌린다. import 를 재실행할 필요는 없다.
validate-migration 은 소스와 타깃 프로젝트명이 같다는 전제로 설계돼 있어, 타깃에서 이름을 바꾼 경우에는 어느 이름을 넣어도 반쪽이 맞지 않는다(UnboundLocalError 2차 버그 포함). 이때는 자동 검증을 포기하고 타깃 UI 에서 프로젝트·Model·Job·파일 개수를 눈으로 확인하는 것으로 갈음한다.
숨은 문자나 정규화 차이도 확인한다.
grep -n '^\[' ~/.cmlutils/*.ini
sed -n '/^\[/p' ~/.cmlutils/export-config.ini | cat -A | head
export LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 PYTHONUTF8=1
username 앞에 공백(들여쓰기)이 있으면 섹션 값이 아니라 이전 값의 연속으로 해석된다. apiv1_key 가 빠지면 인증 자체가 안 된다. 키·값은 줄 첫 칸부터 적는다.
cmlutils 가 프로젝트 설정을 바꾼 것이 아니다. import 가 타깃 프로젝트에서 rsync 런타임으로 전송용 세션을 한 번 띄우고, New Session 화면은 마지막으로 쓴 런타임을 기본으로 보여줄 뿐이다. 원래 런타임으로 세션을 한 번 실행하면 이후 그 값이 기본이 된다. Job/Model/Application 은 런타임이 설정에 저장되므로 각 Settings 에서 직접 확인·수정한다. 커스텀 런타임이 목록에 없다면 마이그레이션 전에 타깃 카탈로그에 등록돼 있었어야 하며, 매핑이 없던 워크로드는 타깃 기본 이미지로 옮겨진다. 모든 프로젝트 이관이 끝난 뒤에만 rsync 런타임을 카탈로그에서 비활성화한다.
output_dir/<프로젝트>/ 아래 폴더만 있고 내용이 비어 있을 수 있다. import 전에 project-data, project-metadata 가 채워졌는지 확인한다.sed -E 's/[a-z0-9.-]+\.<domain>/<HOST>/g' 식으로 가린다.