From 085a0c7ab4639074b7a68cba0e62688b6205c0ce Mon Sep 17 00:00:00 2001 From: biosvos Date: Sat, 8 Aug 2026 18:20:47 +0900 Subject: [PATCH] docs(fhs): split CentOS 6 build and deploy documentation --- fhs/README.md | 221 +----------------------------- fhs/build.6.md | 156 +++++++++++++++++++++ fhs/deploy.6.md | 351 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 510 insertions(+), 218 deletions(-) create mode 100644 fhs/build.6.md create mode 100644 fhs/deploy.6.md diff --git a/fhs/README.md b/fhs/README.md index 165c3da..6168d8e 100644 --- a/fhs/README.md +++ b/fhs/README.md @@ -1,219 +1,4 @@ -# FHS CentOS 6 빌드와 Apache 실행 +# FHS 환경별 문서 -## 0. 실행 준비 - -모든 명령은 같은 셸 세션에서 저장소 루트 디렉터리로 이동한 뒤 실행한다. - -```bash -cd "$(git rev-parse --show-toplevel)" - -RUN_ID="$(date +%Y%m%d%H%M%S)-$$" -FHS_CONTAINER="interactive-fhs-centos6-${RUN_ID}" - -free_port() { - local port=$1 - while (echo >/dev/tcp/127.0.0.1/"$port") 2>/dev/null; do - port=$((port + 1)) - done - printf '%s\n' "$port" -} - -APACHE_PORT="$(free_port 18068)" -``` - -## 1. CentOS 6 빌드 컨테이너 - -```bash -podman pull docker.io/library/centos:centos6 -podman run -d \ - --name "$FHS_CONTAINER" \ - --publish "${APACHE_PORT}:80" \ - --volume "$PWD:/workspace:Z" \ - --workdir /workspace/fhs \ - docker.io/library/centos:centos6 \ - sleep infinity -``` - -## 2. CentOS 6 저장소와 빌드 의존성 - -CentOS 6 종료 후 저장소를 vault로 변경한다. - -```bash -podman exec "$FHS_CONTAINER" cp -p \ - /etc/yum.repos.d/CentOS-Base.repo \ - /etc/yum.repos.d/CentOS-Base.repo.before-vault - -centos_base='^#baseurl=.*\$releasever' -centos_vault='baseurl=http://vault.centos.org/6.10' - -podman exec "$FHS_CONTAINER" sed -i \ - -e 's|^mirrorlist=|#mirrorlist=|' \ - -e "s|${centos_base}|${centos_vault}|" \ - /etc/yum.repos.d/CentOS-Base.repo -``` - -```bash -podman exec "$FHS_CONTAINER" yum install -y \ - gcc gcc-c++ make pkgconfig - -podman exec "$FHS_CONTAINER" yum install -y \ - boost-devel openssl-devel sqlite-devel openldap-devel - -epel_base=http://archives.fedoraproject.org/pub/archive/epel/6 - -podman exec "$FHS_CONTAINER" yum install -y \ - "${epel_base}/x86_64/epel-release-6-8.noarch.rpm" - -epel_old='^#baseurl=.*\$basearch$' -epel_new='baseurl='"${epel_base}"'/$basearch' -podman exec "$FHS_CONTAINER" sed -i \ - -e 's|^mirrorlist=|#mirrorlist=|' \ - -e "s|${epel_old}|${epel_new}|" \ - /etc/yum.repos.d/epel.repo - -podman exec "$FHS_CONTAINER" yum install -y libxml++-devel -``` - -PostgreSQL 9.3 경로와 FHS Makefile에서 사용하는 추가 도구를 준비한다. - -```bash -PG93_BASE=http://download.postgresql.org/pub/repos/yum/9.3/redhat/rhel-6-x86_64 - -podman exec "$FHS_CONTAINER" yum install -y \ - ${PG93_BASE}/postgresql93-9.3.25-1PGDG.rhel6.x86_64.rpm \ - ${PG93_BASE}/postgresql93-libs-9.3.25-1PGDG.rhel6.x86_64.rpm \ - ${PG93_BASE}/postgresql93-devel-9.3.25-1PGDG.rhel6.x86_64.rpm - -podman exec "$FHS_CONTAINER" mkdir -p /user/db -podman exec "$FHS_CONTAINER" ln -s /usr/pgsql-9.3 /user/db/pgsql -podman exec "$FHS_CONTAINER" yum install -y libmcrypt-devel bc - -CentOS 6 기본 Apache 2.2.15와 모듈 빌드 도구를 yum으로 설치한다. - -```bash -podman exec "$FHS_CONTAINER" yum install -y \ - httpd httpd-devel libtool -``` - -`sh-opendav` Makefile의 `/user/service/httpd` 경로를 yum 패키지 경로에 -맞춘다. 소스는 수정하지 않는다. - -```bash -podman exec "$FHS_CONTAINER" bash -lc ' - mkdir -p /user/service/httpd/build /user/service/httpd/include - ln -sfn /usr/bin/libtool /user/service/httpd/build/libtool - for header in /usr/include/httpd/*.h /usr/include/apr-1/*.h; do - ln -sfn "$header" \ - "/user/service/httpd/include/$(basename "$header")" - done -' -``` - -CentOS 6 저장소에는 `libiconv` 패키지가 없으므로, Makefile의 기본 -`-liconv`를 명령행에서 제외하고 `-lmcrypt`만 사용한다. - -`LOCK`/`UNLOCK`을 활성화하기 위해 `sh-opendav/Makefile`의 -`__NOT_USE_LOCKDB__` 정의는 제거한다. - -## 3. FHS 빌드 - -`podman exec -w`로 FHS 작업 디렉터리를 지정해 구성요소를 빌드한다. - -```bash -podman exec -w /workspace/fhs "$FHS_CONTAINER" bash -lc ' - for component in arcmond2 cls csagentd fimngd ftsd; do - make clean -C "${component}" >/dev/null 2>&1 - echo "===== BUILD ${component} =====" - make all -C "${component}" - echo "===== STATUS ${component} $? =====" - done -' - -podman exec -w /workspace/fhs/sh-opendav "$FHS_CONTAINER" bash -lc ' - make clean - make LIBS=-lmcrypt apache-mod-dav-dbms -' -``` - -빌드 결과: - -```text -ftsd 성공 -arcmond2 실패: 제공된 정적 라이브러리의 __inet_addr, __error 심볼 -cls 실패: CentOS 6에 setproctitle 없음 -csagentd 실패: ShmDefine.h의 uint64_t 미정의 및 연쇄 컴파일 오류 -fimngd 성공: 헤더에 ``만 추가 -sh-opendav 성공: apache-mod-dav-dbms target -``` - -## 4. 빌드 산출물 확인 - -```bash -file fhs/ftsd/src/ftsd -file fhs/ftsd/interface/sample/ftsd_test -file fhs/ftsd/lib/libInterCommon.a -file fhs/sh-opendav/.libs/libmod_dav_repos.so -``` - -## 5. CentOS 6 Apache 2.2.15에 sh-opendav 배포 - -빌드된 모듈을 CentOS 6 yum Apache 모듈 디렉터리에 배포하고 -`mod_dbd`와 함께 로드한다. - -```bash -podman exec "$FHS_CONTAINER" cp \ - /workspace/fhs/sh-opendav/.libs/libmod_dav_repos.so \ - /etc/httpd/modules/mod_dav_repos.so - -podman exec "$FHS_CONTAINER" sed -i \ - 's|^#LoadModule dbd_module|LoadModule dbd_module|' \ - /etc/httpd/conf/httpd.conf - -podman exec "$FHS_CONTAINER" sh -lc \ - 'printf "%s\\n" "LoadModule dav_repos_module modules/mod_dav_repos.so" \ - >> /etc/httpd/conf/httpd.conf' - -podman exec "$FHS_CONTAINER" httpd -t -podman exec "$FHS_CONTAINER" httpd -M 2>&1 | \ - grep -E 'dbd_module|dav_repos_module|dav_module|dav_fs_module' -``` - -검증 결과: - -```text -httpd: Syntax OK -dav_module (shared) -dav_fs_module (shared) -dbd_module (shared) -dav_repos_module (shared) -``` - -Apache를 실행하고 기본 HTTP 응답을 확인한다. - -```bash -podman exec -d "$FHS_CONTAINER" /usr/sbin/httpd -DFOREGROUND -curl -sS -D - "http://127.0.0.1:${APACHE_PORT}/" \ - -o /tmp/apache-centos6-body -``` - -CentOS 6 yum Apache 버전은 `Apache/2.2.15`다. `sh-opendav`의 -DB 기반 DAV 요청을 실제로 처리하려면 Apache DBD provider와 FHS DB 설정이 -추가로 필요하다. 위 단계는 모듈 빌드, 배포, Apache 로드까지 검증한다. - -실제 CentOS 6 Apache + `sh-opendav` 검증 결과: - -```text -OPTIONS 200, PROPFIND 207, PROPPATCH 207 -MKCOL 201, PUT 201, GET 200 -COPY 201, MOVE 201, LOCK 200, UNLOCK 204 -DELETE 204 -``` - -`GET` 본문도 `PUT`한 내용과 일치했다. `PROPPATCH`의 `displayname`은 -읽기 전용 속성이므로 응답 내부에 해당 속성의 `409`가 포함되는 것이 정상이다. - -현재 실행 중인 컨테이너 확인: - -```bash -podman ps --filter "name=${FHS_CONTAINER}" -``` +- [CentOS 6 빌드](build.6.md) +- [CentOS 6 배포 및 DAV 검증](deploy.6.md) diff --git a/fhs/build.6.md b/fhs/build.6.md new file mode 100644 index 0000000..6fa43b3 --- /dev/null +++ b/fhs/build.6.md @@ -0,0 +1,156 @@ +# FHS CentOS 6 빌드 + +이 문서는 CentOS 6 컨테이너에서 FHS 소스를 빌드하는 절차만 다룬다. +Apache 설정, PostgreSQL 데이터 준비, 모듈 배포와 DAV 요청 검증은 +[`deploy.6.md`](deploy.6.md)에 있다. + +## 1. CentOS 6 빌드 컨테이너 + +저장소 루트에서 소스를 컨테이너에 복사하지 않고 `PWD`를 `/workspace`로 +마운트한다. `podman exec -w`로 각 빌드 디렉터리를 지정한다. + +```bash +cd "$(git rev-parse --show-toplevel)" + +RUN_ID="$(date +%Y%m%d%H%M%S)-$$" +FHS_CONTAINER="interactive-fhs-centos6-${RUN_ID}" + +podman pull docker.io/library/centos:centos6 +podman run -d \ + --name "$FHS_CONTAINER" \ + --volume "$PWD:/workspace:Z" \ + --workdir /workspace/fhs \ + docker.io/library/centos:centos6 \ + sleep infinity +``` + +CentOS 6 기본 저장소는 종료되었으므로 vault 저장소로 바꾼다. + +```bash +podman exec "$FHS_CONTAINER" cp -p \ + /etc/yum.repos.d/CentOS-Base.repo \ + /etc/yum.repos.d/CentOS-Base.repo.before-vault + +podman exec "$FHS_CONTAINER" sed -i \ + -e 's|^mirrorlist=|#mirrorlist=|' \ + -e 's|^#baseurl=.*\$releasever|baseurl=http://vault.centos.org/6.10|' \ + /etc/yum.repos.d/CentOS-Base.repo +``` + +## 2. 빌드 의존성 + +패키지는 소스와 Makefile에서 실제로 사용하는 컴파일러, 헤더, 라이브러리만 +설치한다. + +| 패키지 | 필요한 빌드 | +| --- | --- | +| `gcc`, `gcc-c++`, `make` | 모든 컴포넌트 | +| `boost-devel` | `arcmond2`, `cls`, `csagentd`, `fimngd`, `ftsd` | +| `sqlite-devel` | `cls` | +| `postgresql93-libs`, `postgresql93-devel` | `cls`, `fimngd` | +| `httpd-devel` | `fimngd`, `sh-opendav` | +| `libtool` | `sh-opendav` | +| `libmcrypt-devel` | `sh-opendav` | +| `bc` | `sh-opendav` | + +근거는 다음과 같다. + +- 모든 Makefile이 C/C++ 컴파일과 재귀 `make`를 사용한다. +- 각 대상의 `lib/Config.cpp`가 `boost/algorithm/string.hpp`를 include한다. +- `cls/src/*.h`가 `sqlite3.h`를 include하고 `-lsqlite3`로 링크한다. +- `cls`와 `fimngd`가 `libpq-fe.h`와 libpq를 사용한다. +- `fimngd`와 `sh-opendav`가 Apache/APR 헤더와 라이브러리를 사용한다. +- `sh-opendav` Makefile이 libtool, `-lmcrypt`, `bc`를 직접 사용한다. + +```bash +podman exec "$FHS_CONTAINER" yum install -y \ + gcc gcc-c++ make boost-devel sqlite-devel bc libmcrypt-devel \ + httpd-devel libtool +``` + +PostgreSQL 9.3의 헤더와 라이브러리를 설치한다. `postgresql93` 본체는 +빌드에 필요하지 않고, DB를 배포하고 `psql`로 확인할 때만 필요하다. + +```bash +PG93_BASE=http://download.postgresql.org/pub/repos/yum/9.3/redhat/rhel-6-x86_64 + +podman exec "$FHS_CONTAINER" yum install -y \ + "${PG93_BASE}/postgresql93-libs-9.3.25-1PGDG.rhel6.x86_64.rpm" \ + "${PG93_BASE}/postgresql93-devel-9.3.25-1PGDG.rhel6.x86_64.rpm" + +podman exec "$FHS_CONTAINER" mkdir -p /user/db +podman exec "$FHS_CONTAINER" ln -sfn /usr/pgsql-9.3 /user/db/pgsql +``` + +`sh-opendav` Makefile가 기대하는 Apache 경로를 yum 설치 경로에 연결한다. + +```bash +podman exec "$FHS_CONTAINER" bash -lc ' + mkdir -p /user/service/httpd/build /user/service/httpd/include + ln -sfn /usr/bin/libtool /user/service/httpd/build/libtool + mkdir -p /user/service/httpd/lib + ln -sfn /usr/lib64/libapr-1.so /user/service/httpd/lib/libapr-1.a + for header in /usr/include/httpd/*.h /usr/include/apr-1/*.h; do + ln -sfn "$header" "/user/service/httpd/include/$(basename "$header")" + done +' +``` + +검증상 `openssl-devel`, `openldap-devel`, `libxml++-devel`, `pkgconfig`는 +현재 빌드 대상의 소스 또는 Makefile에서 사용하지 않았다. 따라서 이 빌드 +절차에는 넣지 않는다. + +## 3. 컴포넌트별 빌드 + +각 컴포넌트를 따로 빌드해서 어느 의존성 또는 기존 소스 문제가 빌드를 +막는지 확인한다. + +```bash +for component in arcmond2 cls csagentd ftsd; do + podman exec -w "/workspace/fhs/${component}" "$FHS_CONTAINER" make clean all +done +``` + +`fimngd`는 Makefile이 정적 `/user/db/pgsql/lib/libpq.a`를 직접 링크한다. +CentOS 6용 PostgreSQL 정적 archive에는 OpenSSL/Kerberos 등의 전이 라이브러리 +심볼이 남으므로, 소스나 Makefile를 바꾸지 않고 동적 `libpq`를 명령행에서 +지정한다. + +```bash +podman exec -w /workspace/fhs/fimngd "$FHS_CONTAINER" make clean +podman exec -w /workspace/fhs/fimngd "$FHS_CONTAINER" \ + make LIBS='-lpthread -L/user/db/pgsql/lib -lpq \ + ../lib/libInterCommon.a /user/service/httpd/lib/libapr-1.a' all +``` + +`sh-opendav`는 `all` target이 아니라 `apache-mod-dav-dbms` target을 사용하고, +CentOS 6 저장소에 없는 `-liconv`는 `LIBS=-lmcrypt`로 대체한다. + +```bash +podman exec -w /workspace/fhs/sh-opendav "$FHS_CONTAINER" make clean +podman exec -w /workspace/fhs/sh-opendav "$FHS_CONTAINER" \ + make LIBS=-lmcrypt apache-mod-dav-dbms +``` + +## 4. 실제 빌드 결과 + +CentOS 6 컨테이너에서 위 명령을 실행한 결과다. + +| 대상 | 결과 | 실패 또는 산출물 | +| --- | --- | --- | +| `arcmond2` | 실패 | 제공된 정적 라이브러리의 Linux 링크 오류 | +| `cls` | 실패 | CentOS 6에서 `setproctitle` 선언이 없음 | +| `csagentd` | 실패 | `ShmDefine.h`의 `uint64_t` 선언 누락 및 연쇄 오류 | +| `fimngd` | 성공 | `src/fimngd` 생성; 동적 `libpq` 링크 명령 사용 | +| `ftsd` | 성공 | `src/ftsd`, `interface/sample/ftsd_test` 생성 | +| `sh-opendav` | 성공 | `.libs/libmod_dav_repos.so` 생성 | + +확인: + +```bash +podman exec -w /workspace/fhs "$FHS_CONTAINER" file \ + fimngd/src/fimngd \ + ftsd/src/ftsd \ + ftsd/interface/sample/ftsd_test \ + sh-opendav/.libs/libmod_dav_repos.so +``` diff --git a/fhs/deploy.6.md b/fhs/deploy.6.md new file mode 100644 index 0000000..4d7fdb1 --- /dev/null +++ b/fhs/deploy.6.md @@ -0,0 +1,351 @@ +# FHS CentOS 6 배포와 DAV 검증 + +이 문서는 빌드된 FHS 산출물을 CentOS 6 Apache 2.2.15에 배포하고, +PostgreSQL 기반 `sh-opendav`의 DAV 기능을 검증하는 절차만 다룬다. +빌드 컨테이너와 컴파일 의존성은 [`build.6.md`](build.6.md)를 먼저 수행한다. + +## 1. 배포 대상 + +`build.6.md`에서 만든 컨테이너와 산출물을 사용한다. + +```bash +FHS_CONTAINER=interactive-fhs-centos6- +DB_CONTAINER=interactive-dav-postgres +``` + +Apache는 FHS 컨테이너 안에서 실행하고 PostgreSQL은 같은 network namespace를 +사용한다. 따라서 Apache와 FHS 데몬은 DB를 `127.0.0.1:5432`로 접근한다. + +## 2. PostgreSQL 런타임 준비 + +실제 서비스에서는 운영 PostgreSQL과 RCDB를 사용한다. 로컬 검증은 PostgreSQL +컨테이너로 대체한다. + +```bash +podman run -d \ + --name "$DB_CONTAINER" \ + --network "container:${FHS_CONTAINER}" \ + -e POSTGRES_USER=syshost \ + -e POSTGRES_PASSWORD=test \ + -e POSTGRES_DB=localdb \ + docker.io/library/postgres:latest + +until podman exec "$DB_CONTAINER" pg_isready -U syshost -d localdb; do + sleep 1 +done +``` + +RCDB 스키마를 넣고 필요한 테이블을 확인한다. 레거시 스키마 파일의 중복 +정의는 허용하되, 필요한 테이블이 실제로 만들어졌는지 확인한다. + +```bash +podman exec -i "$DB_CONTAINER" psql -U syshost -d localdb \ + -v ON_ERROR_STOP=0 -f - < RCDB/DB/scripts/rcdb_schema.sql + +podman exec "$DB_CONTAINER" psql -U syshost -d localdb -c \ + 'select to_regclass('"'"'public.t_dav_lock'"'"'), to_regclass('"'"'public.t_dav_locknull'"'"');' +``` + +DAV 인증과 service cache에 필요한 최소 데이터: + +```bash +podman exec -i "$DB_CONTAINER" psql -U syshost -d localdb <<'SQL' +INSERT INTO t_sms_sp_user + (sp_user_seq, sp_user_id, sp_user_password, reg_datetime, update_datetime) +VALUES + (1, 'davuser', 'test', now(), now()) +ON CONFLICT (sp_user_seq) DO UPDATE SET + sp_user_id = EXCLUDED.sp_user_id, + sp_user_password = EXCLUDED.sp_user_password, + update_datetime = now(); + +INSERT INTO t_sms_sp_svc_product + (sp_svc_tran_id, sp_user_seq, sp_svc_id, sp_svc_begin_date, + sp_svc_end_date, initial_vector, private_key, reg_datetime, + update_datetime, validate_sp_session_id_yn, bandwidth_ctrl_yn, + referer_chk_yn, replication_count, cal_used_depth, uri_ignore_case, + del_file_keep_time) +VALUES + (100, 1, 'svc1', current_date - 1, current_date + 365, + '123456789012345678901234', 'abcdefghijklmnopqrstuvwx', now(), now(), + 'N', 'N', 'N', 1, 0, 'N', 3) +ON CONFLICT (sp_svc_tran_id) DO NOTHING; + +INSERT INTO t_sms_sp_svc_product_val + (sp_svc_tran_id, sp_user_seq, mode, auth_server, auth_path, auth_port) +VALUES + (100, 1, '1000', '', '', '0') +ON CONFLICT (sp_svc_tran_id) DO NOTHING; + +INSERT INTO t_sms_sp_svc_product_band + (sp_svc_tran_id, sp_user_seq, mode) +VALUES + (100, 1, '10') +ON CONFLICT (sp_svc_tran_id) DO NOTHING; +SQL +``` + +서비스 insert trigger가 만든 `t_meta_100`에 루트와 service collection을 +추가한다. 모듈의 `/dav/svc1/` 요청은 이 service collection을 사용한다. + +```bash +podman exec -i "$DB_CONTAINER" psql -U syshost -d localdb <<'SQL' +INSERT INTO t_meta_100 + (sp_user_seq, sp_svc_tran_id, host_name, resource_type, uri, depth, + creation_date, get_lastmodified, deleted_yn, is_cache) +SELECT * FROM (VALUES + (1, 100, 'localhost', 1, '/', 0, + extract(epoch from now())::bigint, + extract(epoch from now())::bigint, 'N', 'N'), + (1, 100, 'localhost', 1, '/100/svc1', 1, + extract(epoch from now())::bigint, + extract(epoch from now())::bigint, 'N', 'N') +) AS seed(sp_user_seq, sp_svc_tran_id, host_name, resource_type, uri, depth, + creation_date, get_lastmodified, deleted_yn, is_cache) +WHERE NOT EXISTS ( + SELECT 1 FROM t_meta_100 existing + WHERE existing.sp_svc_tran_id = seed.sp_svc_tran_id + AND existing.uri = seed.uri +); +SQL +``` + +## 3. FHS 데몬과 저장소 + +`fimngd`는 계정 cache와 FHS shared memory를 Apache 모듈에 제공한다. 운영 +배포에서는 실제 FHS/RCTS 설정을 사용하고, 아래 설정은 로컬 검증용으로만 +사용한다. + +```bash +podman exec "$FHS_CONTAINER" mkdir -p \ + /stg /var/lib/fhs-dav/100 /user/service/etc +podman exec "$FHS_CONTAINER" bash -lc 'cat > /tmp/fhs-dav-test.conf <<"EOF" +[COMMON] +DEFAULT_LOG_DIR = /user/service/logs +LOG_LEVEL = 7 +RCID = test +RCTS_SERVER = 127.0.0.1 +FHS_PORT_MNGCHECK = 14000 +FILE_STORAGE_ROOT = /stg +INTERNAL_NIC_NAME = lo +RCDB_IP = 127.0.0.1 +RCDB_PORT = 5432 +RCDB_DB_NAME = localdb +RCDB_ACCT = syshost +RCDB_ACCT_PW = test +[fimngd] +HOT_CONTENT_REQUEST_TCP_PORT = 14001 +TRANSFER_STAT_SEND_PORT = 14002 +FHS_INFO_REQUEST_PORT = 14003 +MAX_FHS = 1 +MAX_ACCOUNT = 20 +MAX_ANONYMOUS = 1 +IPC_QUEUE_COUNT = 1 +IPC_QUEUE_MAX_SIZE = 500 +EOF +if ! ps axo stat,comm | \ + awk '$2 == "fimngd" && $1 !~ /^Z/ { found = 1 } END { exit !found }'; then + /workspace/fhs/fimngd/src/fimngd \ + -D -c /tmp/fhs-dav-test.conf >/tmp/fimngd-final.log 2>&1 & +fi +' +``` + +실제 FHS가 연결된 환경에서는 RCTS가 FHS 정보를 shared memory에 넣어야 한다. +이 문서는 RCTS/FHS 자체를 배포하지 않으므로, DAV 검증 전 해당 runtime이 +실행 중이고 FHS count가 1 이상인지 확인한다. FHS 정보가 없으면 Apache는 +정상이어도 storage DAV 검증을 완료할 수 없다. + +```bash +podman exec "$FHS_CONTAINER" ps axo pid,stat,comm | \ + awk '$3 == "fimngd" && $2 !~ /^Z/' +podman exec "$DB_CONTAINER" psql -U syshost -d localdb -c \ + 'select sp_user_id, sp_svc_id, sp_svc_tran_id + from t_sms_sp_user join t_sms_sp_svc_product using (sp_user_seq);' +podman exec "$FHS_CONTAINER" sh -lc \ + 'grep -hE "FHS stat updated \\[[^]]*fhs count: [1-9][0-9]*\\]" \ + /user/service/logs/fimngd/fimngd_*.log | tail -n 1' +``` + +## 4. Apache와 sh-opendav 배포 + +CentOS 6 yum Apache 2.2.15와 실행 모듈을 준비한다. 컴파일러와 +`httpd-devel`은 [빌드 문서](build.6.md)에서만 다룬다. + +```bash +podman exec "$FHS_CONTAINER" yum install -y httpd +podman exec "$FHS_CONTAINER" cp \ + /workspace/fhs/sh-opendav/.libs/libmod_dav_repos.so \ + /etc/httpd/modules/mod_dav_repos.so +podman exec "$FHS_CONTAINER" sed -i \ + 's|^#LoadModule dbd_module|LoadModule dbd_module|' \ + /etc/httpd/conf/httpd.conf +``` + +DBD provider와 FHS DAV 설정을 추가한다. + +```bash +podman exec "$FHS_CONTAINER" bash -lc ' +cat > /etc/httpd/conf.d/fhs-opendav-test.conf <<"EOF" +DBDriver pgsql +DBDPersist On +DBDParams "hostaddr=127.0.0.1 dbname=localdb user=syshost password=test" +DBDMin 3 +DBDMax 5 +DBDKeep 4 +DBDExptime 900 + +DavProviderStorageDir /var/lib/fhs-dav +DavProviderBaseURI /dav +DavProviderHostName localhost +DavProviderMaxFHS 1 +DavProviderMaxAnonymous 1 +DavProviderMaxAccount 20 +DavProviderMaxProgess 1 +DavProviderDBCharset UHC +DavProviderCloseInsert off + + + Dav repos + DavDepthInfinity on + Options Indexes FollowSymLinks + AuthType Basic + AuthName "-- OpenDisk Login --" + Order allow,deny + Allow from all + + Require valid-user + + +EOF +grep -q '^LoadModule dav_repos_module modules/mod_dav_repos.so' \ + /etc/httpd/conf/httpd.conf || \ + printf "%s\n" "LoadModule dav_repos_module modules/mod_dav_repos.so" \ + >> /etc/httpd/conf/httpd.conf +chown -R apache:apache /var/lib/fhs-dav +httpd -t +' +``` + +모듈과 Apache가 로드되는지 확인하고 실행한다. + +```bash +podman exec "$FHS_CONTAINER" httpd -M 2>&1 | \ + grep -E 'dbd_module|dav_repos_module|dav_module|dav_fs_module' +if ! podman exec "$FHS_CONTAINER" ps axo stat,comm | \ + awk '$2 == "httpd" && $1 !~ /^Z/ { found = 1 } END { exit !found }'; then + podman exec -d "$FHS_CONTAINER" /usr/sbin/httpd -DFOREGROUND +fi +``` + +예상 모듈 목록: + +```text +dav_module (shared) +dav_fs_module (shared) +dbd_module (shared) +dav_repos_module (shared) +``` + +## 5. DAV 검증 + +검증은 FHS 컨테이너 내부에서 실행한다. 외부 호스트의 `18068`은 별도 Apache +컨테이너 포트일 수 있으므로 사용하지 않는다. + +```bash +podman exec -it "$FHS_CONTAINER" bash +``` + +이 셸 안에서 다음을 실행한다. 검증 URL은 `/dav/svc1/`이며 인증 계정은 +`svc1@davuser:test`다. + +```bash +BASE="http://127.0.0.1/dav/svc1" +printf 'dav-payload\n' >/tmp/dav-payload + +curl -sS -o /dev/null -w 'OPTIONS %{http_code}\n' \ + -X OPTIONS "$BASE/" -u 'svc1@davuser:test' +curl -sS -o /dev/null -w 'MKCOL %{http_code}\n' \ + -X MKCOL "$BASE/check/" -u 'svc1@davuser:test' +curl -sS -o /dev/null -w 'PUT %{http_code}\n' \ + -X PUT "$BASE/check/a.txt" --data-binary @/tmp/dav-payload \ + -u 'svc1@davuser:test' +curl -sS -o /tmp/dav-get -w 'GET %{http_code}\n' \ + "$BASE/check/a.txt" -u 'svc1@davuser:test' +curl -sS -o /dev/null -w 'PROPFIND %{http_code}\n' \ + -X PROPFIND "$BASE/check/" -H 'Depth: 1' -u 'svc1@davuser:test' +cat >/tmp/dav-proppatch.xml <<'EOF' + + + check + +EOF +curl -sS -o /dev/null -w 'PROPPATCH %{http_code}\n' \ + -X PROPPATCH "$BASE/check/a.txt" \ + -H 'Content-Type: application/xml' \ + --data-binary @/tmp/dav-proppatch.xml \ + -u 'svc1@davuser:test' +curl -sS -o /dev/null -w 'COPY %{http_code}\n' \ + -X COPY "$BASE/check/a.txt" \ + -H "Destination: $BASE/check/copied.txt" -u 'svc1@davuser:test' +curl -sS -o /dev/null -w 'MOVE %{http_code}\n' \ + -X MOVE "$BASE/check/copied.txt" \ + -H "Destination: $BASE/check/moved.txt" -u 'svc1@davuser:test' +``` + +LOCK/UNLOCK은 lock token을 받아서 같은 token으로 해제한다. + +```bash +cat >/tmp/dav-lock.xml <<'EOF' + + + + + deploy-check + +EOF + +curl -sS -D /tmp/dav-lock.headers -o /dev/null \ + -w 'LOCK %{http_code}\n' -X LOCK "$BASE/check/a.txt" \ + -H 'Depth: 0' -H 'Timeout: Second-3600' \ + -H 'Content-Type: application/xml' --data-binary @/tmp/dav-lock.xml \ + -u 'svc1@davuser:test' +LOCK_TOKEN="$( + awk ' + BEGIN { IGNORECASE = 1 } + /^Lock-Token:/ { + sub(/^[^:]*:[[:space:]]*/, "") + gsub(/[[:space:]]/, "") + print + } + ' /tmp/dav-lock.headers +)" +curl -sS -o /dev/null -w 'UNLOCK %{http_code}\n' \ + -X UNLOCK "$BASE/check/a.txt" \ + -H "Lock-Token: $LOCK_TOKEN" -u 'svc1@davuser:test' +``` + +마지막으로 자원을 삭제하고 본문을 비교한다. + +```bash +curl -sS -o /dev/null -w 'DELETE moved %{http_code}\n' \ + -X DELETE "$BASE/check/moved.txt" -u 'svc1@davuser:test' +curl -sS -o /dev/null -w 'DELETE original %{http_code}\n' \ + -X DELETE "$BASE/check/a.txt" -u 'svc1@davuser:test' +curl -sS -o /dev/null -w 'DELETE dir %{http_code}\n' \ + -X DELETE "$BASE/check/" -u 'svc1@davuser:test' +cmp /tmp/dav-payload /tmp/dav-get +``` + +실제 검증 결과: + +```text +OPTIONS 200, PROPFIND 207, PROPPATCH 207 +MKCOL 201, PUT 201, GET 200 +COPY 201, MOVE 201, LOCK 200, UNLOCK 204 +DELETE 204 +GET 본문: PUT 내용과 일치 +``` + +`PROPPATCH`의 `displayname`은 모듈에서 읽기 전용 live property로 처리하므로 +전체 응답은 `207`이고 해당 속성의 내부 상태가 `409`인 것은 정상이다.