feature/integracion-cpanel-asrecovery
This commit is contained in:
97
packaging/CloudRestoreAS.spec
Normal file
97
packaging/CloudRestoreAS.spec
Normal 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
18
packaging/LEEME.txt
Normal 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.
|
||||
9
packaging/bundled-versions.json
Normal file
9
packaging/bundled-versions.json
Normal 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"
|
||||
}
|
||||
34
packaging/scripts/build-all.sh
Normal file
34
packaging/scripts/build-all.sh
Normal 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"
|
||||
19
packaging/scripts/docker-build-linux.sh
Executable file
19
packaging/scripts/docker-build-linux.sh
Executable 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
|
||||
'
|
||||
93
packaging/scripts/download-bundled-deps.ps1
Normal file
93
packaging/scripts/download-bundled-deps.ps1
Normal 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
|
||||
58
packaging/scripts/download-bundled-deps.sh
Executable file
58
packaging/scripts/download-bundled-deps.sh
Executable 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"
|
||||
27
packaging/scripts/package-release.sh
Normal file
27
packaging/scripts/package-release.sh
Normal 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"
|
||||
18
packaging/templates/env.default
Normal file
18
packaging/templates/env.default
Normal 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
|
||||
Reference in New Issue
Block a user