fixy i usprwnienia

This commit is contained in:
Mateusz Gruszczyński
2025-03-06 10:38:12 +01:00
parent 4979365617
commit c4b753d4bd
6 changed files with 241 additions and 55 deletions

144
app.py
View File

@@ -7,7 +7,9 @@ from datetime import datetime, timezone, timedelta
from io import StringIO
import socket
import ipaddress
import pytz
from croniter import croniter
from tzlocal import get_localzone
from werkzeug.serving import WSGIRequestHandler
WSGIRequestHandler.server_version = ""
@@ -38,7 +40,8 @@ class Host(db.Model):
key_passphrase = db.Column(db.String(200), nullable=True)
port = db.Column(db.Integer, default=22)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
auto_deploy_enabled = db.Column(db.Boolean, default=True)
auto_backup_enabled = db.Column(db.Boolean, default=True)
@property
def resolved_hostname(self):
try:
@@ -63,8 +66,10 @@ class UserSettings(db.Model):
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), unique=True, nullable=False)
auto_deploy_enabled = db.Column(db.Boolean, default=False)
deploy_interval = db.Column(db.Integer, default=60) # interwał wdrożeń (minuty)
backup_interval = db.Column(db.Integer, default=60) # interwał backupów (minuty)
#deploy_interval = db.Column(db.Integer, default=60) # interwał wdrożeń (minuty)
#backup_interval = db.Column(db.Integer, default=60) # interwał backupów (minuty)
deploy_cron = db.Column(db.String(100), default="12 12 * * *")
backup_cron = db.Column(db.String(100), default="12 12 * * *")
auto_backup_enabled = db.Column(db.Boolean, default=False)
last_deploy_time = db.Column(db.DateTime, nullable=True)
regex_deploy_enabled = db.Column(db.Boolean, default=True)
@@ -170,41 +175,43 @@ def automated_backup_for_host(host):
)
db.session.add(backup)
db.session.commit()
log_entry = DeployLog(
details=f'[BACKUP] Automatic backup created for host {host.hostname}',
user_id=host.user_id
)
db.session.add(log_entry)
db.session.commit()
print(f'Automated backup for host {host.hostname} created successfully.')
except Exception as e:
print(f'Error creating automated backup for host {host.hostname}: {str(e)}')
def automated_backups():
with app.app_context():
logger.debug("Rozpoczynam funkcję automated_backups")
hosts = Host.query.all()
now = datetime.now(timezone.utc)
hosts = Host.query.all()
for host in hosts:
settings = UserSettings.query.filter_by(user_id=host.user_id).first()
if not settings or not settings.auto_backup_enabled:
logger.debug(f"Pomijam host {host.hostname} - auto_backup nie włączone")
# Dodaj warunek: backup dla danego hosta ma być wykonywany tylko, jeśli jest włączony
if not host.auto_backup_enabled:
continue
backup_interval = settings.backup_interval if settings.backup_interval else 60
logger.debug(f"Backup interval dla hosta {host.hostname}: {backup_interval} minut")
settings = UserSettings.query.filter_by(user_id=host.user_id).first()
if not settings or not settings.auto_backup_enabled or not settings.backup_cron:
continue
# Pobieramy ostatni backup dla hosta
last_backup = Backup.query.filter_by(user_id=host.user_id, host_id=host.id)\
.order_by(Backup.created_at.desc()).first()
if last_backup:
last_backup_time = last_backup.created_at
if last_backup_time.tzinfo is None:
# Zakładamy, że zapisany czas jest już w UTC
last_backup_time = last_backup_time.replace(tzinfo=timezone.utc)
diff = (now - last_backup_time).total_seconds()
logger.debug(f"Różnica czasu dla hosta {host.hostname}: {diff} sekund")
base_time = last_backup.created_at
if base_time.tzinfo is None:
base_time = base_time.replace(tzinfo=timezone.utc)
else:
last_backup_time = None
logger.debug(f"Brak poprzedniego backupu dla hosta {host.hostname}")
if (last_backup_time is None) or ((now - last_backup_time).total_seconds() >= backup_interval * 60):
logger.debug(f"Wykonuję backup dla hosta {host.hostname}")
base_time = datetime.now(timezone.utc) - timedelta(minutes=1)
cron = croniter(settings.backup_cron, base_time)
next_backup_time = cron.get_next(datetime)
if now >= next_backup_time:
automated_backup_for_host(host)
db.session.commit()
db.session.expire_all()
else:
logger.debug(f"Backup dla hosta {host.hostname} nie jest jeszcze potrzebny")
def wrap_content_with_comments(content):
@@ -838,22 +845,28 @@ def settings():
if request.method == 'POST':
auto_deploy = request.form.get('auto_deploy')
deploy_interval = request.form.get('deploy_interval')
backup_interval = request.form.get('backup_interval')
deploy_cron = request.form.get('deploy_cron')
auto_backup = request.form.get('auto_backup')
backup_cron = request.form.get('backup_cron')
enable_regex_entries = request.form.get('enable_regex_entries')
retention_val = request.form.get('backup_retention_days', '0')
# Walidacja wyrażeń cron przy pomocy croniter
try:
croniter(deploy_cron)
except Exception as e:
flash("Błędne wyrażenie cron dla deploy: " + str(e), "danger")
return redirect(url_for('settings'))
try:
croniter(backup_cron)
except Exception as e:
flash("Błędne wyrażenie cron dla backup: " + str(e), "danger")
return redirect(url_for('settings'))
user_settings.auto_deploy_enabled = bool(auto_deploy)
user_settings.auto_backup_enabled = bool(auto_backup)
try:
user_settings.deploy_interval = int(deploy_interval)
except ValueError:
user_settings.deploy_interval = 60
try:
user_settings.backup_interval = int(backup_interval)
except ValueError:
user_settings.backup_interval = 60
user_settings.deploy_cron = deploy_cron if deploy_cron else "12 12 * * *"
user_settings.backup_cron = backup_cron if backup_cron else "12 12 * * *"
user_settings.regex_deploy_enabled = bool(enable_regex_entries)
try:
user_settings.backup_retention_days = int(retention_val)
@@ -921,6 +934,9 @@ def deploy_user(user_id):
hosts = Host.query.filter_by(user_id=user_id).all()
for h in hosts:
# Tylko dla serwerów z włączonym auto_deploy
if not h.auto_deploy_enabled:
continue
try:
if h.type == 'linux':
ssh = open_ssh_connection(h)
@@ -934,12 +950,11 @@ def deploy_user(user_id):
sftp.close()
ssh.close()
os.remove(tmp_file_path)
db.session.add(DeployLog(details=f'[LINUX] Updated {h.hostname} for user {user_id}',user_id=user_id))
db.session.add(DeployLog(details=f'[LINUX] Updated {h.hostname} for user {user_id}', user_id=user_id))
elif h.type == 'mikrotik':
wrapped_content = wrap_mikrotik_content(final_content)
deploy_mikrotik(h, wrapped_content)
db.session.add(DeployLog(details=f'[MIKROTIK] Updated {h.hostname} for user {user_id}',user_id=user_id))
db.session.add(DeployLog(details=f'[MIKROTIK] Updated {h.hostname} for user {user_id}', user_id=user_id))
db.session.commit()
except Exception as e:
db.session.add(DeployLog(details=f'Failed to update {h.hostname}: {str(e)} for user {user_id}'))
@@ -1131,20 +1146,61 @@ def delete_regex_host(entry_id):
flash('Row deleted', 'info')
return redirect(url_for('list_regex_hosts'))
@app.route('/delete-selected-backups', methods=['POST'])
def delete_selected_backups():
if 'user_id' not in session:
return redirect(url_for('login'))
selected_ids = request.form.getlist('selected_backups')
for backup_id in selected_ids:
backup = db.session.get(Backup, backup_id)
if backup and backup.user_id == session['user_id']:
db.session.delete(backup)
db.session.commit()
flash('Zaznaczone backupy zostały usunięte.', 'info')
return redirect(url_for('backups'))
@app.route('/update-host-automation/<int:id>', methods=['POST'])
def update_host_automation(id):
if 'user_id' not in session:
return redirect(url_for('login'))
host = db.session.get(Host, id)
if not host or host.user_id != session['user_id']:
flash('Serwer nie istnieje lub nie masz uprawnień', 'danger')
return redirect(url_for('server_list'))
setting = request.form.get('setting')
enabled = request.form.get('enabled') == '1'
if setting == 'auto_deploy':
host.auto_deploy_enabled = enabled
elif setting == 'auto_backup':
host.auto_backup_enabled = enabled
db.session.commit()
flash('Ustawienia automatyzacji zostały zaktualizowane.', 'success')
return redirect(url_for('server_list'))
def scheduled_deployments():
with app.app_context():
now = datetime.now(timezone.utc)
all_settings = UserSettings.query.filter_by(auto_deploy_enabled=True).all()
for setting in all_settings:
last_deploy_time = setting.last_deploy_time
if last_deploy_time:
last_deploy_time = last_deploy_time.replace(tzinfo=timezone.utc)
if not last_deploy_time or now - last_deploy_time >= timedelta(minutes=setting.deploy_interval):
settings_list = UserSettings.query.filter_by(auto_deploy_enabled=True).all()
for setting in settings_list:
if not setting.deploy_cron:
continue
if setting.last_deploy_time:
base_time = setting.last_deploy_time
if base_time.tzinfo is None:
base_time = base_time.replace(tzinfo=timezone.utc)
else:
base_time = datetime(1970,1,1, tzinfo=timezone.utc)
cron = croniter(setting.deploy_cron, base_time)
next_deploy = cron.get_next(datetime)
if now >= next_deploy:
deploy_user(setting.user_id)
setting.last_deploy_time = now
db.session.commit()
scheduler = BackgroundScheduler(timezone="UTC")
scheduler = BackgroundScheduler(timezone=get_localzone())
scheduler.add_job(func=scheduled_deployments, trigger="interval", minutes=1, next_run_time=datetime.now())
scheduler.add_job(func=automated_backups, trigger="interval", minutes=1, next_run_time=datetime.now())
scheduler.add_job(func=cleanup_old_backups, trigger="interval", hours=24, next_run_time=datetime.now())