feature/integracion-cpanel-asrecovery

This commit is contained in:
2026-06-30 11:29:06 -06:00
parent 072be5b5db
commit 034a5ca5bb
35 changed files with 2416 additions and 320 deletions

View File

@@ -0,0 +1,97 @@
# -*- mode: python ; coding: utf-8 -*-
"""PyInstaller spec onefile portable (ejecutar en Windows o Linux según destino)."""
import sys
from pathlib import Path
block_cipher = None
ROOT = Path(SPECPATH).resolve().parent
platform = "windows" if sys.platform == "win32" else "linux"
bundled = ROOT / "packaging" / "bundled" / platform
_assets = ROOT / "packaging" / "assets"
datas = [
(str(ROOT / "packaging" / "templates" / "env.default"), "packaging/templates"),
]
if _assets.is_dir():
for _icon in _assets.iterdir():
if _icon.is_file() and _icon.suffix.lower() in (".png", ".ico"):
datas.append((str(_icon), "packaging/assets"))
binaries = []
seven_dir = bundled / "7zip"
if seven_dir.is_dir():
for item in seven_dir.iterdir():
if item.is_file():
binaries.append((str(item), "bundled/7zip"))
odbc_dir = bundled / "odbc"
if odbc_dir.is_dir():
for item in odbc_dir.rglob("*"):
if not item.is_file():
continue
if item.suffix.lower() in (".msi", ".deb"):
continue
rel = item.relative_to(odbc_dir)
dest = f"bundled/odbc/{rel.parent}".replace("\\", "/")
if str(rel.parent) == ".":
dest = "bundled/odbc"
binaries.append((str(item), dest))
hiddenimports = [
"PySide6",
"pyodbc",
"requests",
"paramiko",
"dotenv",
"cryptography.fernet",
]
if platform == "windows":
hiddenimports.append("win32crypt")
from PyInstaller.utils.hooks import collect_all
pyside_datas, pyside_binaries, pyside_hidden = collect_all("PySide6")
datas += pyside_datas
binaries += pyside_binaries
hiddenimports += pyside_hidden
a = Analysis(
[str(ROOT / "runner.py")],
pathex=[str(ROOT)],
binaries=binaries,
datas=datas,
hiddenimports=hiddenimports,
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False,
)
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
exe = EXE(
pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
[],
name="CloudRestoreAS",
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=False,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
)

18
packaging/LEEME.txt Normal file
View File

@@ -0,0 +1,18 @@
CloudRestoreAS — despliegue portable
=====================================
Windows: copie CloudRestoreAS.exe a la carpeta deseada.
Linux: copie CloudRestoreAS y ejecute chmod +x CloudRestoreAS si hace falta.
1. Ejecute el programa (doble clic o ./CloudRestoreAS).
- Se abre la ventana principal y un icono en la bandeja del sistema.
- El motor arranca automaticamente (CLOUDRESTORE_AUTO_START=true por defecto).
2. Se crean automaticamente: config/, Entrada/, Procesados/, Fallados/, Temp/
3. Edite config/.env con la URL, token e instancia del servicio de bases.
4. Reinicie la aplicacion si cambio la configuracion.
Cerrar la ventana (X) minimiza a la bandeja; la app sigue en ejecucion.
Para salir por completo: clic derecho en el icono de bandeja -> Salir,
o menu Archivo -> Salir.
No requiere Python ni instaladores adicionales en el equipo destino.

View File

@@ -0,0 +1,9 @@
{
"seven_zip": "26.01",
"seven_zip_windows_extra": "https://github.com/ip7z/7zip/releases/download/26.01/7z2601-extra.7z",
"seven_zip_windows_7zr": "https://github.com/ip7z/7zip/releases/download/26.01/7zr.exe",
"seven_zip_linux_x64": "https://github.com/ip7z/7zip/releases/download/26.01/7z2601-linux-x64.tar.xz",
"msodbcsql18_msi": "https://go.microsoft.com/fwlink/?linkid=2281204",
"msodbcsql18_deb": "https://packages.microsoft.com/ubuntu/22.04/prod/pool/main/m/msodbcsql18/msodbcsql18_18.5.1.1-1_amd64.deb",
"unixodbc_deb": "http://archive.ubuntu.com/ubuntu/pool/main/u/unixodbc/unixodbc_2.3.12-1ubuntu0.24.04.1_amd64.deb"
}

View File

@@ -0,0 +1,34 @@
#!/usr/bin/env bash
# Genera ambos artefactos: Linux (local/Docker) y Windows (PowerShell + Python en Windows).
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
RELEASE="$ROOT/dist/release"
mkdir -p "$RELEASE"
echo "=== Build Linux ==="
if [[ -f "$ROOT/build.sh" ]]; then
bash "$ROOT/build.sh"
cp -f "$ROOT/dist/CloudRestoreAS" "$RELEASE/CloudRestoreAS-linux"
chmod +x "$RELEASE/CloudRestoreAS-linux"
fi
echo "=== Build Windows (via PowerShell) ==="
WSL_PATH=$(wslpath -w "$ROOT" 2>/dev/null || echo "")
if [[ -n "$WSL_PATH" ]] && command -v powershell.exe >/dev/null 2>&1; then
powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "
Set-Location '$WSL_PATH'
& 'C:\Users\Hugo Reyes\AppData\Local\Programs\Python\Python313\python.exe' -m pip install -q -r requirements-windows.txt 2>\$null
& .\build.ps1
"
if [[ -f "$ROOT/dist/CloudRestoreAS.exe" ]]; then
cp -f "$ROOT/dist/CloudRestoreAS.exe" "$RELEASE/CloudRestoreAS.exe"
fi
else
echo "Omitido: ejecute build.ps1 en Windows manualmente"
fi
cp -f "$ROOT/packaging/LEEME.txt" "$RELEASE/"
echo ""
echo "Artefactos en: $RELEASE"
ls -la "$RELEASE"

View File

@@ -0,0 +1,19 @@
#!/usr/bin/env bash
# Build Linux onefile dentro de Docker con dependencias Qt del sistema.
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
docker run --rm \
-v "$ROOT:/app" \
-w /app \
ubuntu:22.04 bash -c '
set -e
export DEBIAN_FRONTEND=noninteractive
apt-get update -qq
apt-get install -y -qq \
python3 python3-venv python3-pip curl dpkg-dev binutils unixodbc \
libglib2.0-0 libdbus-1-3 libxkbcommon0 libfontconfig1 libxcb1 libx11-6 \
libxcb-xkb1 libegl1 libgl1 libxi6 libxrender1 libxext6 \
> /dev/null
chmod +x build.sh packaging/scripts/download-bundled-deps.sh
./build.sh
'

View File

@@ -0,0 +1,93 @@
# Descarga 7-Zip Extra y ODBC para empaquetar en CloudRestoreAS.exe
$ErrorActionPreference = "Stop"
$Root = Split-Path (Split-Path $PSScriptRoot -Parent) -Parent
$Versions = Get-Content (Join-Path $Root "packaging\bundled-versions.json") | ConvertFrom-Json
$Bundled = Join-Path $Root "packaging\bundled\windows"
$Seven = Join-Path $Bundled "7zip"
$Odbc = Join-Path $Bundled "odbc"
New-Item -ItemType Directory -Force -Path $Seven, $Odbc | Out-Null
Write-Host "==> 7-Zip Extra ($($Versions.seven_zip))" -ForegroundColor Cyan
if (-not (Test-Path (Join-Path $Seven "7z.exe"))) {
$tmp = Join-Path $env:TEMP "cloudrestore-7z-$(Get-Random)"
New-Item -ItemType Directory -Path $tmp | Out-Null
$sevenR = Join-Path $tmp "7zr.exe"
$extra = Join-Path $tmp "7z-extra.7z"
Invoke-WebRequest -Uri $Versions.seven_zip_windows_7zr -OutFile $sevenR
Invoke-WebRequest -Uri $Versions.seven_zip_windows_extra -OutFile $extra
& $sevenR x $extra ("-o" + $Seven) -y | Out-Null
$x64Exe = Join-Path $Seven "x64\7za.exe"
$x64Dll = Join-Path $Seven "x64\7za.dll"
if (Test-Path $x64Exe) {
Copy-Item $x64Exe (Join-Path $Seven "7z.exe") -Force
Copy-Item $x64Exe (Join-Path $Seven "7za.exe") -Force
}
if (Test-Path $x64Dll) {
Copy-Item $x64Dll (Join-Path $Seven "7z.dll") -Force
Copy-Item $x64Dll (Join-Path $Seven "7za.dll") -Force
}
Remove-Item -Recurse -Force $tmp
Write-Host " 7z.exe en $Seven"
} else {
Write-Host " 7-Zip ya existe"
}
Write-Host "==> ODBC Driver 18 (extraer DLLs del MSI)" -ForegroundColor Cyan
$Msi = Join-Path $Odbc "msodbcsql18.msi"
if (-not (Test-Path (Join-Path $Odbc "msodbcsql18.dll"))) {
if (-not (Test-Path $Msi)) {
Invoke-WebRequest -Uri $Versions.msodbcsql18_msi -OutFile $Msi
}
$extract = Join-Path $Odbc "_msi_extract"
if (Test-Path $extract) { Remove-Item -Recurse -Force $extract }
New-Item -ItemType Directory -Path $extract | Out-Null
$msiArgs = @("/a", "`"$Msi`"", "/qn", "TARGETDIR=`"$extract`"", "IACCEPTMSODBCSQLLICENSETERMS=YES")
$proc = Start-Process msiexec.exe -ArgumentList $msiArgs -Wait -PassThru
if ($proc.ExitCode -ne 0) {
Write-Host " msiexec /a fallo (codigo $($proc.ExitCode)); intentando instalacion silenciosa local..." -ForegroundColor Yellow
$local = Join-Path $Odbc "driver_install"
New-Item -ItemType Directory -Force -Path $local | Out-Null
Start-Process msiexec.exe -ArgumentList "/i", "`"$Msi`"", "/qn", "IACCEPTMSODBCSQLLICENSETERMS=YES", "ADDLOCAL=ALL" -Wait
$sysOdbc = "${env:ProgramFiles}\Microsoft SQL Server\Client SDK\ODBC\170\Tools\Binn"
if (Test-Path $sysOdbc) {
Get-ChildItem $sysOdbc -Filter "*.dll" | Copy-Item -Destination $Odbc -Force
}
$driverDir = "${env:ProgramFiles}\Microsoft SQL Server\Client SDK\ODBC\180\Tools\Binn"
if (Test-Path $driverDir) {
Get-ChildItem $driverDir -Filter "*.dll" | Copy-Item -Destination $Odbc -Force
}
foreach ($dll in @("msodbcsql18.dll", "msodbcsql17.dll")) {
$sys = Join-Path $env:SystemRoot "System32\$dll"
if (Test-Path $sys) { Copy-Item $sys $Odbc -Force }
}
} else {
Get-ChildItem -Path $extract -Recurse -Filter "msodbcsql*.dll" | ForEach-Object {
Copy-Item $_.FullName $Odbc -Force
}
Get-ChildItem -Path $extract -Recurse -Filter "*.dll" | Where-Object {
$_.Name -match "mso|odbc|ssl|crypto|bcp"
} | ForEach-Object { Copy-Item $_.FullName $Odbc -Force -ErrorAction SilentlyContinue }
Remove-Item -Recurse -Force $extract -ErrorAction SilentlyContinue
}
Write-Host " DLLs ODBC en $Odbc"
} else {
Write-Host " ODBC ya existe"
}
if (-not (Test-Path (Join-Path $Odbc "odbcinst.ini"))) {
@"
[ODBC Driver 18 for SQL Server]
Description=Microsoft ODBC Driver 18 for SQL Server
Driver=msodbcsql18.dll
UsageCount=1
[ODBC Driver 17 for SQL Server]
Description=Microsoft ODBC Driver 17 for SQL Server
Driver=msodbcsql17.dll
UsageCount=1
"@ | Set-Content (Join-Path $Odbc "odbcinst.ini") -Encoding ASCII
"[ODBC Data Sources]" | Set-Content (Join-Path $Odbc "odbc.ini") -Encoding ASCII
}
Write-Host "Listo: $Bundled" -ForegroundColor Green

View File

@@ -0,0 +1,58 @@
#!/usr/bin/env bash
# Descarga 7zz y bibliotecas ODBC para empaquetar en el binario Linux.
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
VERSIONS="$ROOT/packaging/bundled-versions.json"
BUNDLED="$ROOT/packaging/bundled/linux"
SEVEN="$BUNDLED/7zip"
ODBC="$BUNDLED/odbc/lib"
mkdir -p "$SEVEN" "$ODBC"
read_url() {
python3 -c "import json; print(json.load(open('$VERSIONS'))['$1'])"
}
LINUX_7Z_URL="$(read_url seven_zip_linux_x64)"
MSODBC_DEB="$(read_url msodbcsql18_deb)"
echo "==> 7-Zip Linux (7zz)"
if [[ ! -f "$SEVEN/7zz" ]]; then
TMP=$(mktemp -d)
curl -fsSL -o "$TMP/7z.tar.xz" "$LINUX_7Z_URL"
tar -xJf "$TMP/7z.tar.xz" -C "$TMP"
cp "$TMP/7zz" "$SEVEN/7zz"
chmod +x "$SEVEN/7zz"
rm -rf "$TMP"
echo " 7zz instalado"
else
echo " 7zz ya existe"
fi
echo "==> ODBC Driver 18 + unixODBC"
if [[ -z "$(ls -A "$ODBC" 2>/dev/null || true)" ]]; then
TMP=$(mktemp -d)
cd "$TMP"
curl -fsSL -o msodbcsql18.deb "$MSODBC_DEB"
if command -v apt-get >/dev/null 2>&1; then
export DEBIAN_FRONTEND=noninteractive
apt-get update -qq
apt-get install -y -qq unixodbc dpkg-dev > /dev/null 2>&1 || true
if dpkg -l unixodbc 2>/dev/null | grep -q ^ii; then
find /usr/lib -name 'libodbc*.so*' -exec cp -P {} "$ODBC/" \; 2>/dev/null || true
find /usr/lib -name 'libodbcinst*.so*' -exec cp -P {} "$ODBC/" \; 2>/dev/null || true
fi
fi
dpkg-deb -x msodbcsql18.deb msodbcsql
find msodbcsql -name '*.so*' -exec cp -P {} "$ODBC/" \;
cd "$ROOT"
rm -rf "$TMP"
echo " Bibliotecas ODBC en $ODBC"
else
echo " ODBC ya existe"
fi
echo "Listo: $BUNDLED"

View File

@@ -0,0 +1,27 @@
#!/usr/bin/env bash
# Empaqueta artefactos en dist/release/
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
RELEASE="$ROOT/dist/release"
mkdir -p "$RELEASE"
[[ -f "$ROOT/dist/CloudRestoreAS.exe" ]] && cp -f "$ROOT/dist/CloudRestoreAS.exe" "$RELEASE/"
[[ -f "$ROOT/dist/CloudRestoreAS" ]] && cp -f "$ROOT/dist/CloudRestoreAS" "$RELEASE/CloudRestoreAS-linux" && chmod +x "$RELEASE/CloudRestoreAS-linux"
cp -f "$ROOT/packaging/LEEME.txt" "$RELEASE/"
python3 <<'PY'
import zipfile
from pathlib import Path
release = Path("dist/release")
if (release / "CloudRestoreAS.exe").exists():
with zipfile.ZipFile(release / "CloudRestoreAS-win.zip", "w", zipfile.ZIP_DEFLATED) as z:
z.write(release / "CloudRestoreAS.exe", "CloudRestoreAS.exe")
z.write(release / "LEEME.txt", "LEEME.txt")
PY
if [[ -f "$RELEASE/CloudRestoreAS-linux" ]]; then
tar czf "$RELEASE/CloudRestoreAS-linux.tar.gz" -C "$RELEASE" CloudRestoreAS-linux LEEME.txt
fi
echo "Release en: $RELEASE"
ls -lh "$RELEASE"

View File

@@ -0,0 +1,18 @@
# CloudRestoreAS — configuración local (editar y reiniciar la app)
# Arranca el motor al abrir (la ventana siempre se muestra salvo START_MINIMIZED=true)
CLOUDRESTORE_AUTO_START=true
CLOUDRESTORE_START_MINIMIZED=false
CLOUDRESTORE_REGISTER_AUTOSTART=true
# Servicio PANEL_BASES_ANEXO24
CLOUDRESTORE_PANEL_API_URL=
CLOUDRESTORE_PANEL_API_TOKEN=
CLOUDRESTORE_PANEL_INSTANCE_KEY=
CLOUDRESTORE_PANEL_VERIFY_SSL=false
# Carpetas (se crean automáticamente junto al ejecutable)
CLOUDRESTORE_INPUT_FOLDER={APP_DIR}/Entrada
CLOUDRESTORE_PROCESSED_FOLDER={APP_DIR}/Procesados
CLOUDRESTORE_FAILED_FOLDER={APP_DIR}/Fallados
CLOUDRESTORE_EXTRACT_FOLDER={APP_DIR}/Temp