Files
CloudRecoveryAS/app/config/odbc_setup.py

85 lines
3.0 KiB
Python

"""Configura ODBC portable desde config/odbc/."""
import os
import sys
from pathlib import Path
from ..constants import IS_WINDOWS, ODBC_DIR
from ..utils.logger import app_logger
def _write_portable_odbc_ini(odbc_dir: Path) -> None:
"""Genera odbcinst.ini mínimo si no existe."""
inst = odbc_dir / "odbcinst.ini"
if inst.exists():
return
if IS_WINDOWS:
driver_path = odbc_dir / "msodbcsql18.dll"
if not driver_path.exists():
for candidate in odbc_dir.glob("msodbcsql*.dll"):
driver_path = candidate
break
driver_line = str(driver_path.resolve()) if driver_path.exists() else "msodbcsql18.dll"
content = f"""[ODBC Driver 18 for SQL Server]
Description=Microsoft ODBC Driver 18 for SQL Server
Driver={driver_line}
UsageCount=1
"""
else:
# Los .so embebidos viven en config/odbc/lib (no en la raíz). Buscar ahí
# primero y usar SIEMPRE la ruta absoluta del archivo versionado real
# (p. ej. libmsodbcsql-18.5.so.1.1); un nombre suelto como
# "libmsodbcsql-18.so" no resuelve porque ese symlink apunta a /opt.
lib_dir = odbc_dir / "lib"
search_dirs = [d for d in (lib_dir, odbc_dir) if d.is_dir()]
so_path = None
for base in search_dirs:
# Preferir el archivo real versionado sobre symlinks (que pueden estar rotos).
candidates = sorted(
(p for p in base.glob("libmsodbcsql-18*.so*") if p.is_file() and not p.is_symlink()),
key=lambda p: len(p.name),
reverse=True,
)
if not candidates:
candidates = [p for p in base.glob("libmsodbcsql-18*.so*") if p.exists()]
if candidates:
so_path = candidates[0]
break
driver_line = str(so_path.resolve()) if so_path else "libmsodbcsql-18.so"
content = f"""[ODBC Driver 18 for SQL Server]
Description=Microsoft ODBC Driver 18 for SQL Server
Driver={driver_line}
UsageCount=1
"""
inst.write_text(content, encoding="utf-8")
ini = odbc_dir / "odbc.ini"
if not ini.exists():
ini.write_text("[ODBC Data Sources]\n", encoding="utf-8")
def configure_odbc_environment() -> None:
"""Apunta pyodbc al driver embebido en config/odbc si está disponible."""
if not ODBC_DIR.is_dir():
return
lib_dir = ODBC_DIR / "lib"
if lib_dir.is_dir():
existing = os.environ.get("LD_LIBRARY_PATH", "")
lib_path = str(lib_dir.resolve())
if lib_path not in existing.split(":"):
os.environ["LD_LIBRARY_PATH"] = (
f"{lib_path}:{existing}" if existing else lib_path
)
_write_portable_odbc_ini(ODBC_DIR)
odbc_sys = str(ODBC_DIR.resolve())
os.environ["ODBCSYSINI"] = odbc_sys
os.environ["ODBCINI"] = str((ODBC_DIR / "odbc.ini").resolve())
if IS_WINDOWS:
os.environ["PATH"] = odbc_sys + os.pathsep + os.environ.get("PATH", "")
app_logger.debug(f"ODBC configurado: ODBCSYSINI={odbc_sys}")