diff --git a/backend/app/services/scheduler/schedule_tenant.py b/backend/app/services/scheduler/schedule_tenant.py index 8b025fc..2ad0c12 100644 --- a/backend/app/services/scheduler/schedule_tenant.py +++ b/backend/app/services/scheduler/schedule_tenant.py @@ -929,85 +929,93 @@ def run_tenant_check(schedule_log_id: int, db: Session): # ── [4] NC container + DB 驗證 + OIDC 設定 ───────────────────────── pg_db = f"nc_{tenant.code}_db" - try: - nc_state = docker.check_container_ssh(nc_name) - if nc_state is None: - # 容器不存在 → 確保 docker-compose.yml + DB + 部署 - logger.info(f"NC {nc_name}: not found, ensuring compose/DB and deploying") - _ensure_tenant_compose(tenant, is_active) - _ensure_nc_db(pg_host, pg_db, pg_port) - ok = docker.ssh_compose_up(tenant.code) - result.nc_result = True if ok else False - if not ok: - fail_reasons.append("nc: deploy failed") + if tenant.is_manager: + # Manager 租戶無需 NC/OO 容器,直接標記成功 + result.nc_result = True + result.nc_done_at = now_tw() + result.office_result = True + result.office_done_at = now_tw() + else: + try: + nc_state = docker.check_container_ssh(nc_name) + if nc_state is None: + # 容器不存在 → 確保 docker-compose.yml + DB + 部署 + logger.info(f"NC {nc_name}: not found, ensuring compose/DB and deploying") + _ensure_tenant_compose(tenant, is_active) + _ensure_nc_db(pg_host, pg_db, pg_port) + ok = docker.ssh_compose_up(tenant.code) + result.nc_result = True if ok else False + if not ok: + fail_reasons.append("nc: deploy failed") + else: + # 部署成功後驗證 NC 是否正確使用 PostgreSQL + if not _nc_db_check(nc_name, pg_host, pg_db, tenant.domain, pg_port): + result.nc_result = False + fail_reasons.append("nc: installed but not using pgsql") + elif nc_state is False: + # 容器存在但已停止 → 重啟 + logger.info(f"NC {nc_name}: stopped, restarting") + ok = docker.ssh_compose_up(tenant.code) + result.nc_result = True if ok else False + if not ok: + fail_reasons.append("nc: start failed") else: - # 部署成功後驗證 NC 是否正確使用 PostgreSQL - if not _nc_db_check(nc_name, pg_host, pg_db, tenant.domain, pg_port): + # 容器正常運行 → 驗證 DB 類型(防止 sqlite3 殘留問題) + db_ok = _nc_db_check(nc_name, pg_host, pg_db, tenant.domain, pg_port) + if not db_ok: result.nc_result = False - fail_reasons.append("nc: installed but not using pgsql") - elif nc_state is False: - # 容器存在但已停止 → 重啟 - logger.info(f"NC {nc_name}: stopped, restarting") - ok = docker.ssh_compose_up(tenant.code) - result.nc_result = True if ok else False - if not ok: - fail_reasons.append("nc: start failed") - else: - # 容器正常運行 → 驗證 DB 類型(防止 sqlite3 殘留問題) - db_ok = _nc_db_check(nc_name, pg_host, pg_db, tenant.domain, pg_port) - if not db_ok: - result.nc_result = False - fail_reasons.append("nc: DB check failed (possible sqlite3 issue)") - else: - result.nc_result = True - if kc_drive_secret: - if not _nc_initialized(nc_name): - # 首次初始化:語言 + Apps + OIDC + SSO 強制模式 + OO 整合 - oo_url = (f"https://office-{tenant.code}.ease.taipei" if is_active - else f"https://office-{tenant.code}.lab.taipei") - ok = _nc_initialize(nc_name, kc_host, realm, kc_drive_secret, tenant.domain, - oo_name, oo_url, is_active) - if not ok: - fail_reasons.append("nc: initialization failed") - else: - # 已初始化:僅同步 OIDC secret(確保與 KC 一致) - ok = _configure_nc_oidc(nc_name, kc_host, realm, kc_drive_secret, tenant.domain) - if not ok: - fail_reasons.append("nc: OIDC sync failed") - result.nc_done_at = now_tw() - except Exception as e: - result.nc_result = False - result.nc_done_at = now_tw() - fail_reasons.append(f"nc: {e}") + fail_reasons.append("nc: DB check failed (possible sqlite3 issue)") + else: + result.nc_result = True + if kc_drive_secret: + if not _nc_initialized(nc_name): + # 首次初始化:語言 + Apps + OIDC + SSO 強制模式 + OO 整合 + oo_url = (f"https://office-{tenant.code}.ease.taipei" if is_active + else f"https://office-{tenant.code}.lab.taipei") + ok = _nc_initialize(nc_name, kc_host, realm, kc_drive_secret, tenant.domain, + oo_name, oo_url, is_active) + if not ok: + fail_reasons.append("nc: initialization failed") + else: + # 已初始化:僅同步 OIDC secret(確保與 KC 一致) + ok = _configure_nc_oidc(nc_name, kc_host, realm, kc_drive_secret, tenant.domain) + if not ok: + fail_reasons.append("nc: OIDC sync failed") + result.nc_done_at = now_tw() + except Exception as e: + result.nc_result = False + result.nc_done_at = now_tw() + fail_reasons.append(f"nc: {e}") - # ── [5] OO container ───────────────────────────────────────────────── - try: - oo_state = docker.check_container_ssh(oo_name) - if oo_state is None: - ok = docker.ssh_compose_up(tenant.code) - result.office_result = True if ok else False - if not ok: - fail_reasons.append("oo: deploy failed") - elif oo_state is False: - ok = docker.ssh_compose_up(tenant.code) - result.office_result = True if ok else False - if not ok: - fail_reasons.append("oo: start failed") - else: - result.office_result = True - result.office_done_at = now_tw() - except Exception as e: - result.office_result = False - result.office_done_at = now_tw() - fail_reasons.append(f"oo: {e}") + # ── [5] OO container ───────────────────────────────────────────────── + try: + oo_state = docker.check_container_ssh(oo_name) + if oo_state is None: + ok = docker.ssh_compose_up(tenant.code) + result.office_result = True if ok else False + if not ok: + fail_reasons.append("oo: deploy failed") + elif oo_state is False: + ok = docker.ssh_compose_up(tenant.code) + result.office_result = True if ok else False + if not ok: + fail_reasons.append("oo: start failed") + else: + result.office_result = True + result.office_done_at = now_tw() + except Exception as e: + result.office_result = False + result.office_done_at = now_tw() + fail_reasons.append(f"oo: {e}") # ── [6] Quota (OO disk + PG DB size) ──────────────────────────────── - try: - oo_gb = docker.get_oo_disk_usage_gb(oo_name) or 0.0 - pg_gb = _get_pg_db_size_gb(pg_host, pg_db, pg_port) or 0.0 - result.quota_usage = round(oo_gb + pg_gb, 3) - except Exception as e: - logger.warning(f"Quota check failed for {tenant.code}: {e}") + if not tenant.is_manager: + try: + oo_gb = docker.get_oo_disk_usage_gb(oo_name) or 0.0 + pg_gb = _get_pg_db_size_gb(pg_host, pg_db, pg_port) or 0.0 + result.quota_usage = round(oo_gb + pg_gb, 3) + except Exception as e: + logger.warning(f"Quota check failed for {tenant.code}: {e}") if fail_reasons: result.fail_reason = "; ".join(fail_reasons)