532 lines
18 KiB
Markdown
532 lines
18 KiB
Markdown
# AutoBackups Project
|
|
|
|
## Overview
|
|
AutoBackups is a Python application designed to automate the backup of Simatic S7 projects and other user-defined directories. The application leverages the Everything API to efficiently locate files and manage backups based on user-defined configurations.
|
|
|
|
## Features
|
|
- Monitors specified directories for Simatic S7 files (*.s7p) and other user-defined directories.
|
|
- Automatically compresses and backs up projects on a configurable schedule (daily, hourly, 3-hour, 7-hour intervals, startup, or manual).
|
|
- Supports manual backup triggers.
|
|
- Skips projects with files in use and retries after one hour.
|
|
- Maintains a two-stage hash system: first checking *.s7p files, then all files to avoid unnecessary backups.
|
|
- User-friendly web interface built with Flask for configuration and status monitoring.
|
|
- Comprehensive logging system with timestamped log files.
|
|
|
|
## Project Structure
|
|
```
|
|
├── .logs/ # Application logs with startup timestamps
|
|
├── src
|
|
│ ├── app.py # Main entry point of the Flask application
|
|
│ ├── models
|
|
│ │ └── __init__.py # Data models for configuration and directories
|
|
│ ├── routes
|
|
│ │ └── __init__.py # API routes for backup operations
|
|
│ ├── services
|
|
│ │ └── __init__.py # Business logic for backups
|
|
│ └── utils
|
|
│ └── __init__.py # Utility functions for hashing and file access
|
|
├── static
|
|
│ ├── css # CSS files for styling
|
|
│ └── js # JavaScript files for client-side functionality
|
|
├── templates
|
|
│ └── index.html # Main HTML template for the web interface
|
|
├── config.json # Global configuration settings for the application
|
|
├── projects.json # Per-project configuration, schedules, and hash storage
|
|
├── requirements.txt # Python dependencies
|
|
└── README.md # Project documentation
|
|
```
|
|
|
|
## Installation
|
|
1. Clone the repository:
|
|
```
|
|
git clone <repository-url>
|
|
cd autobackups
|
|
```
|
|
|
|
2. Create a Miniconda environment:
|
|
```
|
|
conda create --name autobackups python=3.12
|
|
conda activate autobackups
|
|
```
|
|
|
|
3. Install the required packages:
|
|
```
|
|
pip install -r requirements.txt
|
|
```
|
|
|
|
4. Configure the application by editing `config.json` to specify directories to monitor and backup settings.
|
|
|
|
## Usage
|
|
- Start the Flask application:
|
|
```
|
|
python src/app.py
|
|
```
|
|
|
|
- Access the web interface at `http://localhost:5120` to configure settings and monitor backup statuses.
|
|
|
|
## Contributing
|
|
Contributions are welcome! Please submit a pull request or open an issue for any enhancements or bug fixes.
|
|
|
|
## License
|
|
This project is licensed under the MIT License. See the LICENSE file for details.
|
|
|
|
# AutoBackups - Especificación Técnica Detallada
|
|
|
|
## Resumen Ejecutivo
|
|
AutoBackups es una aplicación Python que automatiza el backup de proyectos Simatic S7 y directorios definidos por el usuario, utilizando la API de Everything para búsqueda eficiente de archivos y un sistema de hash inteligente para evitar backups innecesarios.
|
|
|
|
## Arquitectura del Sistema
|
|
|
|
### 1. Componentes Principales
|
|
|
|
#### 1.1 Motor de Búsqueda (Everything API)
|
|
- **Librería**: PyEverything wrapper
|
|
- **DLL Local**: `Everything-SDK\dll\Everything64.dll`
|
|
- **Función**: Localizar archivos *.s7p en directorios de observación
|
|
- **Optimización**: Evitar último nivel del árbol para archivos .s7p
|
|
- **Ventaja**: Aprovecha el índice existente de Everything para búsquedas instantáneas
|
|
|
|
#### 1.2 Sistema de Hash en Dos Etapas
|
|
**Etapa 1**: Hash rápido de archivos *.s7p
|
|
- Solo verifica MD5 de (timestamp + tamaño) de archivos .s7p
|
|
- Si no hay cambios → no se procede con backup
|
|
- Si hay cambios → procede a Etapa 2
|
|
|
|
**Etapa 2**: Hash completo del proyecto
|
|
- Calcula MD5 de (timestamp + tamaño) de todos los archivos del directorio
|
|
- Compara con último hash almacenado
|
|
- Solo hace backup si hay diferencias
|
|
|
|
#### 1.3 Scheduler de Background
|
|
- **daily**: Una vez al día a hora configurada
|
|
- **hourly**: Cada hora
|
|
- **3-hour**: Cada 3 horas
|
|
- **7-hour**: Cada 7 horas
|
|
- **startup**: Al iniciar la aplicación
|
|
- **manual**: Solo bajo demanda del usuario
|
|
- **Escaneos**: Automáticos cada 1 hora
|
|
- **Backups**: Mínimo cada 10 minutos
|
|
- **Prioridad**: Baja prioridad de sistema
|
|
|
|
### 2. Estructura de Datos
|
|
|
|
#### 2.1 config.json (Configuración Global)
|
|
```json
|
|
{
|
|
"observation_directories": [
|
|
{
|
|
"path": "C:\\Projects\\Siemens",
|
|
"type": "siemens_s7",
|
|
"enabled": true,
|
|
"description": "Directorio principal de proyectos Siemens"
|
|
},
|
|
{
|
|
"path": "D:\\Engineering\\Projects",
|
|
"type": "siemens_s7",
|
|
"enabled": true,
|
|
"description": "Proyectos de ingeniería adicionales"
|
|
},
|
|
{
|
|
"path": "C:\\Important\\Documentation",
|
|
"type": "manual",
|
|
"enabled": true,
|
|
"description": "Documentación importante para backup manual"
|
|
}
|
|
],
|
|
"backup_destination": "D:\\Backups\\AutoBackups",
|
|
"global_settings": {
|
|
"default_schedule": "daily",
|
|
"default_schedule_time": "02:00",
|
|
"retry_delay_hours": 1,
|
|
"backup_timeout_minutes": 0,
|
|
"min_free_space_mb": 100,
|
|
"scan_interval_minutes": 60,
|
|
"min_backup_interval_minutes": 10
|
|
},
|
|
"everything_api": {
|
|
"dll_path": "Everything-SDK\\dll\\Everything64.dll",
|
|
"enabled": true,
|
|
"search_depth": -1,
|
|
"skip_last_level_for_s7p": true
|
|
},
|
|
"web_interface": {
|
|
"host": "127.0.0.1",
|
|
"port": 5000,
|
|
"debug": false
|
|
},
|
|
"logging": {
|
|
"level": "INFO",
|
|
"max_log_files": 30,
|
|
"log_rotation_days": 30
|
|
},
|
|
"backup_options": {
|
|
"compression_level": 6,
|
|
"include_subdirectories": true,
|
|
"preserve_directory_structure": true,
|
|
"hash_algorithm": "md5",
|
|
"hash_includes": ["timestamp", "size"],
|
|
"backup_type": "complete",
|
|
"process_priority": "low",
|
|
"sequential_execution": true,
|
|
"filename_format": "HH-MM-SS_projects.zip",
|
|
"date_format": "YYYY-MM-DD"
|
|
}
|
|
}
|
|
```
|
|
|
|
#### 2.2 projects.json (Estado de Proyectos)
|
|
```json
|
|
{
|
|
"metadata": {
|
|
"version": "1.0",
|
|
"last_updated": "2025-09-01T08:30:15Z",
|
|
"total_projects": 0
|
|
},
|
|
"projects": [
|
|
{
|
|
"id": "example_project_001",
|
|
"name": "PLC_MainLine_Example",
|
|
"path": "C:\\Projects\\Siemens\\LineA\\Project1",
|
|
"type": "siemens_s7",
|
|
"s7p_file": "C:\\Projects\\Siemens\\LineA\\Project1\\project.s7p",
|
|
"observation_directory": "C:\\Projects\\Siemens",
|
|
"relative_path": "LineA\\Project1",
|
|
"backup_path": "LineA\\Project1",
|
|
"schedule_config": {
|
|
"schedule": "daily",
|
|
"schedule_time": "02:00",
|
|
"enabled": true,
|
|
"next_scheduled_backup": "2025-09-02T02:00:00Z"
|
|
},
|
|
"backup_history": {
|
|
"last_backup_date": "2025-09-01T02:15:30Z",
|
|
"last_backup_file": "D:\\Backups\\AutoBackups\\LineA\\Project1\\2025-09-01\\02-15-30_projects.zip",
|
|
"backup_count": 5,
|
|
"last_successful_backup": "2025-09-01T02:15:30Z"
|
|
},
|
|
"hash_info": {
|
|
"last_s7p_hash": "abc123def456789",
|
|
"last_full_hash": "def789ghi012345",
|
|
"last_s7p_timestamp": "2025-08-31T14:30:00Z",
|
|
"last_s7p_size": 2048576,
|
|
"last_scan_timestamp": "2025-09-01T02:10:00Z",
|
|
"file_count": 1247,
|
|
"total_size_bytes": 125847296
|
|
},
|
|
"status": {
|
|
"current_status": "ready",
|
|
"last_error": null,
|
|
"retry_count": 0,
|
|
"next_retry": null,
|
|
"files_in_use": false,
|
|
"exclusivity_check_passed": true,
|
|
"last_status_update": "2025-09-01T02:15:35Z"
|
|
},
|
|
"discovery_info": {
|
|
"discovered_date": "2025-09-01T08:30:15Z",
|
|
"discovery_method": "everything_api",
|
|
"auto_discovered": true
|
|
}
|
|
}
|
|
],
|
|
"statistics": {
|
|
"total_backups_created": 15,
|
|
"total_backup_size_mb": 2450.5,
|
|
"average_backup_time_seconds": 45.2,
|
|
"last_global_scan": "2025-09-01T08:30:15Z",
|
|
"projects_with_errors": 0,
|
|
"projects_pending_retry": 0
|
|
}
|
|
}
|
|
```
|
|
|
|
### 3. Flujo de Operación
|
|
|
|
#### 3.1 Inicio de Aplicación
|
|
1. Cargar configuración desde `config.json`
|
|
2. Cargar estado de proyectos desde `projects.json`
|
|
3. Inicializar logger con timestamp de inicio
|
|
4. Escanear directorios de observación usando Everything API
|
|
5. Actualizar lista de proyectos detectados
|
|
6. Iniciar scheduler
|
|
7. Iniciar interfaz web Flask
|
|
|
|
#### 4.2 Proceso de Backup
|
|
1. **Verificación de Espacio**: Verificar mínimo 100MB libres
|
|
2. **Verificación de Acceso .s7p**: Intentar comprimir solo archivo .s7p
|
|
3. **Hash Etapa 1**: Verificar MD5 de (timestamp + tamaño) del archivo .s7p
|
|
4. **Hash Etapa 2**: Si Etapa 1 detecta cambios, verificar hash completo
|
|
5. **Compresión**: Crear archivo ZIP con estructura específica preservada
|
|
6. **Almacenamiento**: Guardar en `backup_destination/ProjectPath/YYYY-MM-DD/HH-MM-SS_projects.zip`
|
|
7. **Actualización**: Actualizar hashes y timestamps en `projects.json`
|
|
|
|
#### 3.3 Gestión de Errores
|
|
- **Archivos en uso**: Marcar proyecto para reintento en 1 hora
|
|
- **Errores de permisos**: Log de error y notificación en interfaz
|
|
- **Errores de espacio**: Verificar espacio disponible antes de backup
|
|
|
|
### 4. Interfaz Web
|
|
|
|
#### 4.1 Dashboard Principal
|
|
- **Lista de Proyectos**: Tabla con estado, último backup, próximo backup
|
|
- **Controles Globales**: Backup manual global, pausar/reanudar scheduler
|
|
- **Estadísticas**: Total de proyectos, backups exitosos, errores
|
|
|
|
#### 4.2 Configuración de Proyectos
|
|
- **Habilitación/Deshabilitación**: Toggle por proyecto
|
|
- **Configuración de Schedule**: Dropdown con opciones de frecuencia
|
|
- **Backup Manual**: Botón de backup inmediato por proyecto
|
|
|
|
#### 4.3 Logs y Monitoreo
|
|
- **Log Viewer**: Mostrar logs recientes con filtros por nivel
|
|
- **Estado del Sistema**: Información de Everything API, espacio en disco
|
|
|
|
### 5. Estructura de Backup
|
|
|
|
#### 5.1 Nomenclatura de Archivos (Estructura Específica)
|
|
```
|
|
backup_destination/
|
|
├── LineA/
|
|
│ └── Project1/
|
|
│ ├── 2025-09-01/
|
|
│ │ ├── 02-15-30_projects.zip
|
|
│ │ └── 14-30-15_projects.zip
|
|
│ └── 2025-09-02/
|
|
│ └── 02-15-45_projects.zip
|
|
└── LineB/
|
|
└── Project2/
|
|
└── 2025-09-01/
|
|
└── 08-20-10_projects.zip
|
|
```
|
|
|
|
#### 5.2 Contenido del ZIP
|
|
```
|
|
02-15-30_projects.zip
|
|
└── LineA/
|
|
└── Project1/
|
|
├── project.s7p
|
|
├── subfolder1/
|
|
└── subfolder2/
|
|
```
|
|
|
|
### 6. Tecnologías y Librerías
|
|
|
|
#### 6.1 Python Core
|
|
- **Python**: 3.12
|
|
- **Framework Web**: Flask
|
|
- **Scheduler**: APScheduler
|
|
- **Compresión**: zipfile (biblioteca estándar)
|
|
|
|
#### 6.2 Librerías Específicas
|
|
- **Everything API**: PyEverything wrapper con DLL local
|
|
- **Hashing**: hashlib MD5 para (timestamp + tamaño)
|
|
- **Config**: json (biblioteca estándar)
|
|
- **Logging**: logging (biblioteca estándar)
|
|
- **File Access Check**: Intento de compresión + verificación .s7p
|
|
- **Process Priority**: pywin32 para baja prioridad
|
|
- **Disk Space**: psutil para monitoreo de espacio libre
|
|
|
|
#### 6.3 Frontend
|
|
- **HTML/CSS/JavaScript**: Vanilla (sin React por simplicidad)
|
|
- **AJAX**: Para comunicación con Flask API
|
|
- **Bootstrap**: Para estilizado responsivo
|
|
|
|
### 7. Consideraciones de Seguridad
|
|
|
|
#### 7.1 Acceso a Archivos
|
|
- Verificación de permisos antes de backup
|
|
- Manejo seguro de rutas para evitar path traversal
|
|
- Logs de todos los accesos a archivos
|
|
|
|
#### 7.2 Interfaz Web
|
|
- Solo acceso local (127.0.0.1)
|
|
- No autenticación requerida (uso local únicamente)
|
|
- Validación de inputs en formularios
|
|
|
|
### 8. Logging y Monitoreo
|
|
|
|
#### 8.1 Estructura de Logs
|
|
```
|
|
.logs/
|
|
├── autobackups_2025-09-01_08-30-15.log
|
|
├── autobackups_2025-09-02_08-30-22.log
|
|
└── ...
|
|
```
|
|
|
|
#### 8.2 Niveles de Log
|
|
- **INFO**: Inicio/fin de backups, descubrimiento de proyectos
|
|
- **WARNING**: Archivos en uso, reintentos
|
|
- **ERROR**: Fallos de backup, errores de configuración
|
|
- **DEBUG**: Detalles de hashes, operaciones de archivos
|
|
|
|
### 9. Instalación y Despliegue
|
|
|
|
#### 9.1 Entorno Miniconda
|
|
```bash
|
|
conda create --name autobackups python=3.12
|
|
conda activate autobackups
|
|
pip install -r requirements.txt
|
|
```
|
|
|
|
#### 9.2 Ejecución
|
|
- **Desarrollo**: `python src/app.py`
|
|
- **Producción**: `pythonw.exe src/app.py` (sin consola)
|
|
- **Como servicio**: Futuro enhancement con `python-windows-service`
|
|
|
|
### 10. Roadmap de Desarrollo
|
|
|
|
#### Fase 1: Core Backend
|
|
- [ ] Integración con Everything API
|
|
- [ ] Sistema de hash en dos etapas
|
|
- [ ] Motor de backup básico
|
|
- [ ] Scheduler con APScheduler
|
|
|
|
#### Fase 2: Interfaz Web
|
|
- [ ] Dashboard básico con Flask
|
|
- [ ] API REST para operaciones CRUD
|
|
- [ ] Frontend con HTML/JS/Bootstrap
|
|
|
|
#### Fase 3: Características Avanzadas
|
|
- [ ] Logs web viewer
|
|
- [ ] Configuración avanzada de directorios
|
|
- [ ] Estadísticas y reportes
|
|
|
|
#### Fase 4: Optimizaciones
|
|
- [ ] Ejecución como servicio Windows
|
|
- [ ] Notificaciones por email
|
|
- [ ] Backup incremental
|
|
|
|
Este documento será la base para el desarrollo del proyecto AutoBackups.
|
|
|
|
|
|
# AutoBackups - Preguntas Técnicas Pendientes
|
|
|
|
## Preguntas Críticas para el Desarrollo
|
|
|
|
### 1. Everything API - Integración
|
|
**Pregunta**: ¿Everything está instalado y funcionando en el sistema objetivo?
|
|
**Impacto**: Si no está disponible, necesitaremos un método alternativo de búsqueda de archivos.
|
|
**Opciones**:
|
|
- Usar `python-everything` si Everything está disponible
|
|
- Implementar búsqueda recursiva con `os.walk()` como fallback
|
|
- Usar `pathlib` con `glob` patterns
|
|
|
|
**Decisión necesaria**: ¿Podemos asumir que Everything estará disponible o necesitamos fallback?
|
|
|
|
### 2. Estructura de Backup - Clarificación de Rutas
|
|
**Pregunta**: Si tenemos un archivo en `C:\Projects\Siemens\LineA\Project1\project.s7p`, ¿el backup debe ser?
|
|
**Opción A**:
|
|
```
|
|
backup_destination/2025-09-01_14-30-15/Projects_Siemens_LineA_Project1.zip
|
|
└── Projects/Siemens/LineA/Project1/...
|
|
```
|
|
**Opción B**:
|
|
```
|
|
backup_destination/2025-09-01_14-30-15/LineA_Project1.zip
|
|
└── LineA/Project1/...
|
|
```
|
|
|
|
**Decisión necesaria**: ¿Qué estructura prefieres?
|
|
|
|
### 3. Configuración de Schedules - Granularidad
|
|
**Pregunta**: ¿Los schedules deben ser configurables a nivel de:
|
|
- Por directorio de observación (todos los proyectos de un directorio)
|
|
- Por proyecto individual
|
|
- Ambos (global con override por proyecto)
|
|
|
|
**Decisión necesaria**: ¿Qué nivel de granularidad necesitas?
|
|
|
|
### 4. Hash de Archivos - Algoritmo y Almacenamiento
|
|
**Pregunta**: Para el sistema de hash en dos etapas:
|
|
- ¿Usamos MD5 (rápido) o SHA256 (más seguro) para los hashes?
|
|
- ¿El hash incluye solo timestamp o también tamaño de archivo?
|
|
- ¿Cómo manejamos archivos que se mueven dentro del proyecto?
|
|
|
|
**Decisión necesaria**: ¿Qué balance entre velocidad y precisión prefieres?
|
|
|
|
### 5. Detección de Archivos en Uso - Método
|
|
**Pregunta**: Para detectar archivos bloqueados, ¿prefieres:
|
|
**Opción A**: Intentar abrir cada archivo en modo escritura exclusiva
|
|
**Opción B**: Usar `lsof` (Linux) / `handle.exe` (Windows) para listar archivos abiertos
|
|
**Opción C**: Solo verificar el archivo .s7p principal
|
|
|
|
**Decisión necesaria**: ¿Qué método consideras más apropiado?
|
|
|
|
### 6. Manejo de Proyectos Grandes - Performance
|
|
**Pregunta**: ¿Hay límites que debamos considerar?
|
|
- Tamaño máximo de proyecto para backup
|
|
- Tiempo máximo de backup
|
|
- Número máximo de archivos por proyecto
|
|
|
|
**Decisión necesaria**: ¿Necesitamos algún tipo de throttling o límites?
|
|
|
|
### 7. Configuración de Directorios - Recursividad
|
|
**Pregunta**: Cuando especificamos un directorio de observación como `C:\Projects`, ¿debemos:
|
|
- Buscar solo en subdirectorios inmediatos
|
|
- Buscar recursivamente en toda la jerarquía
|
|
- Permitir configurar la profundidad de búsqueda
|
|
|
|
**Decisión necesaria**: ¿Qué comportamiento prefieres por defecto?
|
|
|
|
### 8. Backup Incremental vs Completo
|
|
**Pregunta**: ¿Todos los backups deben ser completos o consideras backup incremental?
|
|
- Backup completo: Todo el proyecto cada vez
|
|
- Backup incremental: Solo archivos modificados
|
|
|
|
**Decisión necesaria**: ¿Preferencia por simplicidad o eficiencia de espacio?
|
|
|
|
### 9. Web Interface - Características Específicas
|
|
**Pregunta**: ¿Qué funcionalidades son prioritarias en la interfaz web?
|
|
**Must-have**:
|
|
- Lista de proyectos con estado
|
|
- Trigger manual de backup
|
|
- Ver logs básicos
|
|
|
|
**Nice-to-have**:
|
|
- Configurar schedules por proyecto
|
|
- Ver progreso de backup en tiempo real
|
|
- Estadísticas históricas
|
|
- Configurar nuevos directorios
|
|
|
|
**Decisión necesaria**: ¿Cuáles son must-have vs nice-to-have?
|
|
|
|
### 10. Error Handling - Estrategias de Recuperación
|
|
**Pregunta**: ¿Cómo manejar errores específicos?
|
|
- Espacio insuficiente en destino de backup
|
|
- Pérdida de conexión con Everything
|
|
- Corrupción de archivos de configuración
|
|
- Falla durante compresión
|
|
|
|
**Decisión necesaria**: ¿Qué nivel de robustez necesitas?
|
|
|
|
### 11. Startup Behavior - Inicialización
|
|
**Pregunta**: Al iniciar la aplicación:
|
|
- ¿Debe hacer un escaneo completo inmediatamente?
|
|
- ¿Debe esperar al primer schedule programado?
|
|
- ¿Debe permitir configurar el comportamiento de startup?
|
|
|
|
**Decisión necesaria**: ¿Qué comportamiento prefieres al iniciar?
|
|
|
|
### 12. Multi-threading - Concurrencia
|
|
**Pregunta**: ¿Los backups deben ejecutarse:
|
|
- Secuencialmente (uno por vez)
|
|
- En paralelo (múltiples simultáneos)
|
|
- Con límite configurable de concurrencia
|
|
|
|
**Decisión necesaria**: ¿Qué balance entre velocidad y recursos del sistema?
|
|
|
|
## Próximos Pasos
|
|
Una vez que tengas respuestas a estas preguntas, podremos:
|
|
1. Finalizar el diseño técnico
|
|
2. Crear el `requirements.txt` definitivo
|
|
3. Comenzar con la implementación por fases
|
|
4. Definir el plan de testing
|
|
|
|
¿Podrías revisar estas preguntas y darme tus preferencias para cada una?
|
|
|
|
|
|
Para ejecutar el programa se puede usar:
|
|
|
|
'conda activate autobackups ; python src/app.py'
|
|
|