Initial commit: CloudRestoreAS v1.0.0 - Aplicación completa de restauración automática SQL Server
This commit is contained in:
446
SCRIPTS.md
Normal file
446
SCRIPTS.md
Normal file
@@ -0,0 +1,446 @@
|
||||
# Ejemplos de Scripts de Automatización para CloudRestoreAS
|
||||
|
||||
## 1. Script de Deployment Completo
|
||||
|
||||
```powershell
|
||||
# deploy_cloudrestore.ps1
|
||||
# Script para desplegar CloudRestoreAS en un servidor nuevo
|
||||
|
||||
param(
|
||||
[string]$InstallPath = "C:\CloudRestore",
|
||||
[string]$InputFolder = "C:\Backups\Entrada",
|
||||
[string]$ProcessedFolder = "C:\Backups\Procesados",
|
||||
[string]$SQLServer = "localhost",
|
||||
[string]$SQLDataFolder = "C:\Program Files\Microsoft SQL Server\MSSQL16.MSSQLSERVER\MSSQL\DATA"
|
||||
)
|
||||
|
||||
Write-Host "Desplegando CloudRestoreAS..." -ForegroundColor Cyan
|
||||
|
||||
# Crear directorios
|
||||
$folders = @($InstallPath, $InputFolder, $ProcessedFolder)
|
||||
foreach ($folder in $folders) {
|
||||
if (-not (Test-Path $folder)) {
|
||||
New-Item -ItemType Directory -Path $folder -Force | Out-Null
|
||||
Write-Host "✓ Creado: $folder" -ForegroundColor Green
|
||||
}
|
||||
}
|
||||
|
||||
# Copiar archivos de la aplicación
|
||||
Copy-Item -Path ".\*" -Destination $InstallPath -Recurse -Force -Exclude @("venv", "build", "dist", "*.log")
|
||||
|
||||
# Instalar dependencias
|
||||
Set-Location $InstallPath
|
||||
python -m venv venv
|
||||
.\venv\Scripts\pip.exe install -r requirements.txt
|
||||
|
||||
Write-Host "✓ CloudRestoreAS instalado en: $InstallPath" -ForegroundColor Green
|
||||
```
|
||||
|
||||
## 2. Configuración Automática de Nodos desde CSV
|
||||
|
||||
```powershell
|
||||
# import_nodes.ps1
|
||||
# Importa nodos desde un archivo CSV
|
||||
|
||||
param(
|
||||
[string]$CSVPath = "nodes.csv"
|
||||
)
|
||||
|
||||
# Formato CSV:
|
||||
# NodeName,DatabaseName,Active,Notes
|
||||
# BACKUP_VENTAS.ZIP,Ventas_DB,1,Base de datos de ventas
|
||||
# BACKUP_INVENTARIO.ZIP,Inventario_DB,1,Sistema de inventario
|
||||
|
||||
$script = @"
|
||||
import csv
|
||||
from app.db.node_repository import NodeRepository
|
||||
|
||||
with open('$CSVPath', 'r', encoding='utf-8') as f:
|
||||
reader = csv.DictReader(f)
|
||||
for row in reader:
|
||||
NodeRepository.create(
|
||||
node_name=row['NodeName'].upper(),
|
||||
db_name=row['DatabaseName'],
|
||||
notes=row.get('Notes', '')
|
||||
)
|
||||
if row.get('Active', '1') == '0':
|
||||
NodeRepository.update(row['NodeName'].upper(), active=False)
|
||||
print(f"Importado: {row['NodeName']} -> {row['DatabaseName']}")
|
||||
"@
|
||||
|
||||
python -c $script
|
||||
|
||||
Write-Host "✓ Nodos importados desde $CSVPath" -ForegroundColor Green
|
||||
```
|
||||
|
||||
## 3. Monitoreo y Alertas
|
||||
|
||||
```powershell
|
||||
# monitor_cloudrestore.ps1
|
||||
# Monitorea el estado de CloudRestoreAS y envía alertas
|
||||
|
||||
param(
|
||||
[string]$EmailTo = "admin@empresa.com",
|
||||
[string]$EmailFrom = "cloudrestore@empresa.com",
|
||||
[string]$SMTPServer = "smtp.empresa.com"
|
||||
)
|
||||
|
||||
$script = @"
|
||||
from app.db.job_repository import JobRepository
|
||||
from app.db.event_repository import EventRepository
|
||||
import json
|
||||
|
||||
stats = JobRepository.get_stats()
|
||||
recent_errors = EventRepository.get_all(level='ERROR', limit=10)
|
||||
|
||||
result = {
|
||||
'stats': stats,
|
||||
'errors': [{'created_at': e.created_at, 'message': e.message} for e in recent_errors]
|
||||
}
|
||||
|
||||
print(json.dumps(result))
|
||||
"@
|
||||
|
||||
$result = python -c $script | ConvertFrom-Json
|
||||
|
||||
# Verificar si hay problemas
|
||||
$shouldAlert = $false
|
||||
$alertMessage = "CloudRestoreAS - Reporte de Estado`n`n"
|
||||
|
||||
if ($result.stats.failed -gt 0) {
|
||||
$shouldAlert = $true
|
||||
$alertMessage += "⚠️ Jobs Fallados: $($result.stats.failed)`n"
|
||||
}
|
||||
|
||||
if ($result.errors.Count -gt 0) {
|
||||
$shouldAlert = $true
|
||||
$alertMessage += "`nÚltimos Errores:`n"
|
||||
foreach ($error in $result.errors) {
|
||||
$alertMessage += " - $($error.created_at): $($error.message)`n"
|
||||
}
|
||||
}
|
||||
|
||||
$alertMessage += "`nEstadísticas:`n"
|
||||
$alertMessage += " Total: $($result.stats.total)`n"
|
||||
$alertMessage += " Completados: $($result.stats.completed)`n"
|
||||
$alertMessage += " En Cola: $($result.stats.queued)`n"
|
||||
$alertMessage += " Ejecutando: $($result.stats.running)`n"
|
||||
|
||||
if ($shouldAlert) {
|
||||
# Enviar email
|
||||
Send-MailMessage -To $EmailTo -From $EmailFrom -Subject "CloudRestoreAS - Alerta" `
|
||||
-Body $alertMessage -SmtpServer $SMTPServer
|
||||
|
||||
Write-Host "⚠️ Alerta enviada" -ForegroundColor Yellow
|
||||
} else {
|
||||
Write-Host "✓ Todo OK" -ForegroundColor Green
|
||||
}
|
||||
```
|
||||
|
||||
## 4. Limpieza Automática
|
||||
|
||||
```powershell
|
||||
# cleanup_old_jobs.ps1
|
||||
# Limpia jobs antiguos y archivos procesados
|
||||
|
||||
param(
|
||||
[int]$DaysToKeep = 30,
|
||||
[string]$ProcessedFolder = "C:\Backups\Procesados",
|
||||
[switch]$CleanDatabase
|
||||
)
|
||||
|
||||
Write-Host "Limpiando archivos antiguos (más de $DaysToKeep días)..." -ForegroundColor Cyan
|
||||
|
||||
# Limpiar archivos procesados
|
||||
$cutoffDate = (Get-Date).AddDays(-$DaysToKeep)
|
||||
$filesRemoved = 0
|
||||
|
||||
Get-ChildItem $ProcessedFolder -Recurse -File | Where-Object {
|
||||
$_.LastWriteTime -lt $cutoffDate
|
||||
} | ForEach-Object {
|
||||
Remove-Item $_.FullName -Force
|
||||
$filesRemoved++
|
||||
}
|
||||
|
||||
Write-Host "✓ Archivos eliminados: $filesRemoved" -ForegroundColor Green
|
||||
|
||||
# Limpiar registros de base de datos (opcional)
|
||||
if ($CleanDatabase) {
|
||||
$script = @"
|
||||
from app.db.database import db
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
cutoff = (datetime.utcnow() - timedelta(days=$DaysToKeep)).isoformat()
|
||||
|
||||
# Eliminar job_steps de jobs antiguos completados
|
||||
db.execute('''
|
||||
DELETE FROM job_steps
|
||||
WHERE job_id IN (
|
||||
SELECT job_id FROM jobs
|
||||
WHERE status = 'completed' AND created_at < ?
|
||||
)
|
||||
''', (cutoff,))
|
||||
|
||||
# Eliminar jobs antiguos completados
|
||||
result = db.execute('''
|
||||
DELETE FROM jobs
|
||||
WHERE status = 'completed' AND created_at < ?
|
||||
''', (cutoff,))
|
||||
|
||||
print(f"Jobs eliminados: {result.rowcount}")
|
||||
"@
|
||||
|
||||
$result = python -c $script
|
||||
Write-Host "✓ $result" -ForegroundColor Green
|
||||
}
|
||||
```
|
||||
|
||||
## 5. Backup y Restore de Configuración
|
||||
|
||||
```powershell
|
||||
# backup_config.ps1
|
||||
# Respalda la configuración y base de datos
|
||||
|
||||
param(
|
||||
[string]$BackupPath = "C:\Backups\CloudRestore_Config"
|
||||
)
|
||||
|
||||
$timestamp = Get-Date -Format "yyyyMMdd_HHmmss"
|
||||
$backupDir = Join-Path $BackupPath $timestamp
|
||||
|
||||
New-Item -ItemType Directory -Path $backupDir -Force | Out-Null
|
||||
|
||||
# Backup de base de datos SQLite
|
||||
Copy-Item "data\app.db" "$backupDir\app.db"
|
||||
|
||||
# Backup de logs recientes
|
||||
Copy-Item "logs\*.log" $backupDir -ErrorAction SilentlyContinue
|
||||
|
||||
Write-Host "✓ Backup creado en: $backupDir" -ForegroundColor Green
|
||||
|
||||
# Comprimir
|
||||
Compress-Archive -Path $backupDir -DestinationPath "$backupDir.zip"
|
||||
Remove-Item $backupDir -Recurse -Force
|
||||
|
||||
Write-Host "✓ Backup comprimido: $backupDir.zip" -ForegroundColor Green
|
||||
```
|
||||
|
||||
```powershell
|
||||
# restore_config.ps1
|
||||
# Restaura configuración desde backup
|
||||
|
||||
param(
|
||||
[string]$BackupZip
|
||||
)
|
||||
|
||||
if (-not (Test-Path $BackupZip)) {
|
||||
Write-Error "Archivo de backup no encontrado: $BackupZip"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Extraer
|
||||
$tempDir = Join-Path $env:TEMP "cloudrestore_restore"
|
||||
Expand-Archive -Path $BackupZip -DestinationPath $tempDir -Force
|
||||
|
||||
# Restaurar base de datos
|
||||
Copy-Item "$tempDir\app.db" "data\app.db" -Force
|
||||
|
||||
Write-Host "✓ Configuración restaurada desde: $BackupZip" -ForegroundColor Green
|
||||
|
||||
# Limpiar
|
||||
Remove-Item $tempDir -Recurse -Force
|
||||
```
|
||||
|
||||
## 6. Verificación de Salud del Sistema
|
||||
|
||||
```powershell
|
||||
# health_check.ps1
|
||||
# Verifica que todos los componentes estén funcionando
|
||||
|
||||
Write-Host "CloudRestoreAS - Health Check" -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
|
||||
$healthOK = $true
|
||||
|
||||
# 1. Verificar carpetas configuradas
|
||||
$script = @"
|
||||
from app.db.config_repository import ConfigRepository
|
||||
import json
|
||||
config = ConfigRepository.get('app_config', {})
|
||||
print(json.dumps(config.get('paths', {})))
|
||||
"@
|
||||
|
||||
$paths = python -c $script | ConvertFrom-Json
|
||||
|
||||
foreach ($key in $paths.PSObject.Properties.Name) {
|
||||
$path = $paths.$key
|
||||
if ($path -and (Test-Path $path)) {
|
||||
Write-Host "✓ $key : $path" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host "✗ $key : $path (no existe)" -ForegroundColor Red
|
||||
$healthOK = $false
|
||||
}
|
||||
}
|
||||
|
||||
# 2. Verificar 7-Zip
|
||||
$sevenZipPath = $paths.seven_zip_exe
|
||||
if ($sevenZipPath -and (Test-Path $sevenZipPath)) {
|
||||
Write-Host "✓ 7-Zip: $sevenZipPath" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host "✗ 7-Zip no configurado" -ForegroundColor Red
|
||||
$healthOK = $false
|
||||
}
|
||||
|
||||
# 3. Verificar conexión SQL
|
||||
$scriptSQL = @"
|
||||
from app.db.config_repository import ConfigRepository
|
||||
from app.sql.sql_manager import SQLServerManager
|
||||
from app.utils.crypto import decrypt_password
|
||||
|
||||
config = ConfigRepository.get('app_config', {})
|
||||
sql_config = config.get('sql', {})
|
||||
|
||||
manager = SQLServerManager(
|
||||
server=sql_config.get('server', 'localhost'),
|
||||
use_windows_auth=sql_config.get('use_windows_auth', True),
|
||||
username=sql_config.get('username'),
|
||||
password=decrypt_password(sql_config.get('password_encrypted', '')) if sql_config.get('password_encrypted') else None
|
||||
)
|
||||
|
||||
success, error = manager.test_connection()
|
||||
print('OK' if success else f'ERROR: {error}')
|
||||
"@
|
||||
|
||||
$sqlResult = python -c $scriptSQL
|
||||
|
||||
if ($sqlResult -eq 'OK') {
|
||||
Write-Host "✓ SQL Server: Conexión OK" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host "✗ SQL Server: $sqlResult" -ForegroundColor Red
|
||||
$healthOK = $false
|
||||
}
|
||||
|
||||
# 4. Verificar base de datos
|
||||
$scriptDB = @"
|
||||
from app.db.database import db
|
||||
conn = db.get_connection()
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("SELECT COUNT(*) FROM jobs")
|
||||
job_count = cursor.fetchone()[0]
|
||||
print(job_count)
|
||||
"@
|
||||
|
||||
try {
|
||||
$jobCount = python -c $scriptDB
|
||||
Write-Host "✓ Base de datos: $jobCount jobs registrados" -ForegroundColor Green
|
||||
} catch {
|
||||
Write-Host "✗ Base de datos: Error de acceso" -ForegroundColor Red
|
||||
$healthOK = $false
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
if ($healthOK) {
|
||||
Write-Host "✓ Sistema Saludable" -ForegroundColor Green
|
||||
exit 0
|
||||
} else {
|
||||
Write-Host "✗ Se encontraron problemas" -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
```
|
||||
|
||||
## 7. Generación de Reportes
|
||||
|
||||
```powershell
|
||||
# generate_report.ps1
|
||||
# Genera reporte de actividad en HTML
|
||||
|
||||
param(
|
||||
[string]$OutputPath = "report.html",
|
||||
[int]$Days = 7
|
||||
)
|
||||
|
||||
$script = @"
|
||||
from app.db.job_repository import JobRepository
|
||||
from datetime import datetime, timedelta
|
||||
import json
|
||||
|
||||
cutoff = (datetime.utcnow() - timedelta(days=$Days)).isoformat()
|
||||
|
||||
jobs = JobRepository.get_all(limit=1000)
|
||||
recent_jobs = [j for j in jobs if j.created_at >= cutoff]
|
||||
|
||||
stats = {
|
||||
'total': len(recent_jobs),
|
||||
'completed': len([j for j in recent_jobs if j.status == 'completed']),
|
||||
'failed': len([j for j in recent_jobs if 'failed' in j.status]),
|
||||
'avg_time': sum([j.total_ms or 0 for j in recent_jobs if j.status == 'completed']) / max(len([j for j in recent_jobs if j.status == 'completed']), 1)
|
||||
}
|
||||
|
||||
print(json.dumps(stats))
|
||||
"@
|
||||
|
||||
$stats = python -c $script | ConvertFrom-Json
|
||||
|
||||
$html = @"
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>CloudRestoreAS - Reporte</title>
|
||||
<style>
|
||||
body { font-family: Arial, sans-serif; margin: 40px; }
|
||||
.stat { display: inline-block; margin: 20px; padding: 20px; border: 2px solid #ddd; border-radius: 8px; }
|
||||
.stat h2 { margin: 0; font-size: 48px; color: #0066cc; }
|
||||
.stat p { margin: 5px 0 0 0; color: #666; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>CloudRestoreAS - Reporte de Actividad</h1>
|
||||
<p>Período: Últimos $Days días</p>
|
||||
<p>Generado: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')</p>
|
||||
|
||||
<div>
|
||||
<div class="stat">
|
||||
<h2>$($stats.total)</h2>
|
||||
<p>Total Jobs</p>
|
||||
</div>
|
||||
<div class="stat">
|
||||
<h2>$($stats.completed)</h2>
|
||||
<p>Completados</p>
|
||||
</div>
|
||||
<div class="stat">
|
||||
<h2>$($stats.failed)</h2>
|
||||
<p>Fallados</p>
|
||||
</div>
|
||||
<div class="stat">
|
||||
<h2>$([math]::Round($stats.avg_time / 1000, 1))s</h2>
|
||||
<p>Tiempo Promedio</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
"@
|
||||
|
||||
$html | Out-File -FilePath $OutputPath -Encoding UTF8
|
||||
|
||||
Write-Host "✓ Reporte generado: $OutputPath" -ForegroundColor Green
|
||||
|
||||
# Abrir en navegador
|
||||
Start-Process $OutputPath
|
||||
```
|
||||
|
||||
## Uso de Scripts con Task Scheduler
|
||||
|
||||
```powershell
|
||||
# Ejemplo: Programar monitoreo cada hora
|
||||
$action = New-ScheduledTaskAction -Execute "PowerShell.exe" `
|
||||
-Argument "-File C:\CloudRestore\scripts\monitor_cloudrestore.ps1"
|
||||
|
||||
$trigger = New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval (New-TimeSpan -Hours 1)
|
||||
|
||||
Register-ScheduledTask -TaskName "CloudRestore_Monitor" `
|
||||
-Action $action -Trigger $trigger -RunLevel Highest
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Estos scripts son ejemplos que puedes adaptar a tus necesidades específicas.
|
||||
Reference in New Issue
Block a user