3158 lines
120 KiB
Python
3158 lines
120 KiB
Python
from django.shortcuts import render, redirect, get_object_or_404
|
||
from django.contrib import messages
|
||
from django.views.decorators.http import require_http_methods
|
||
from django.db import models
|
||
from django.db.models import Q
|
||
from django.utils import timezone
|
||
|
||
from .backup import job
|
||
from .models import SSHCredential, Project, SSHLog, Customer, Backup
|
||
from .ssh_client import SSHManager
|
||
from django.http import JsonResponse, HttpResponse
|
||
from django.http import HttpResponseNotAllowed
|
||
|
||
import logging
|
||
from django.core.files.storage import FileSystemStorage
|
||
import os
|
||
import json
|
||
from django.views.decorators.csrf import csrf_exempt # Ekleyin
|
||
from django.contrib.auth.decorators import login_required
|
||
from django.core.exceptions import ValidationError
|
||
from google.oauth2 import service_account
|
||
from googleapiclient.discovery import build
|
||
from googleapiclient.http import MediaFileUpload
|
||
import zipfile
|
||
import shutil
|
||
from datetime import datetime
|
||
from django.conf import settings
|
||
import tempfile # Ekleyin
|
||
from io import BytesIO
|
||
from django.utils import timezone
|
||
from django.views.decorators.http import require_GET
|
||
|
||
from django.views.decorators.csrf import ensure_csrf_cookie
|
||
|
||
# Logger oluştur
|
||
logger = logging.getLogger(__name__)
|
||
|
||
# Utils import
|
||
try:
|
||
from utils.whois_tools import get_domain_expiration_date
|
||
WHOIS_TOOLS_AVAILABLE = True
|
||
except ImportError as e:
|
||
WHOIS_TOOLS_AVAILABLE = False
|
||
# Logger henüz tanımlanmamış olabilir, print kullan
|
||
print(f"WHOIS tools import hatası: {e}")
|
||
|
||
@require_GET
|
||
def get_host(request, host_id):
|
||
from .models import SSHCredential
|
||
try:
|
||
host = SSHCredential.objects.get(id=host_id)
|
||
return JsonResponse({
|
||
'success': True,
|
||
'host': {
|
||
'id': host.id,
|
||
'hostname': host.hostname,
|
||
'username': host.username,
|
||
'password': '', # Güvenlik için boş bırak
|
||
'port': host.port,
|
||
'base_path': host.base_path,
|
||
'created_at': host.created_at.strftime('%Y-%m-%d %H:%M:%S') if host.created_at else '',
|
||
'is_online': host.is_online,
|
||
'last_check': host.last_check.strftime('%Y-%m-%d %H:%M:%S') if host.last_check else ''
|
||
}
|
||
})
|
||
except SSHCredential.DoesNotExist:
|
||
return JsonResponse({'success': False, 'message': 'Host bulunamadı'})
|
||
|
||
@ensure_csrf_cookie
|
||
def dashboard(request):
|
||
"""Dashboard sayfası - özet ve istatistikler"""
|
||
projects = Project.objects.all().select_related('customer', 'ssh_credential')
|
||
ssh_credentials = SSHCredential.objects.all()
|
||
customers = Customer.objects.filter(is_active=True)
|
||
recent_logs = SSHLog.objects.all().order_by('-created_at')[:10]
|
||
|
||
# İstatistikler
|
||
active_sites_count = projects.filter(is_site_active=True).count()
|
||
online_hosts_count = ssh_credentials.filter(connection_status='connected').count()
|
||
recent_backups = projects.filter(last_backup__isnull=False).order_by('-last_backup')[:6]
|
||
|
||
context = {
|
||
'projects': projects,
|
||
'ssh_credentials': ssh_credentials,
|
||
'customers': customers,
|
||
'recent_logs': recent_logs,
|
||
'active_sites_count': active_sites_count,
|
||
'online_hosts_count': online_hosts_count,
|
||
'recent_backups': recent_backups,
|
||
}
|
||
return render(request, 'ssh_manager/dashboard.html', context)
|
||
|
||
# Bağlantı kontrolü yapıldı mı kontrolü için global değişken
|
||
_connection_checked = False
|
||
|
||
@ensure_csrf_cookie
|
||
def project_list(request):
|
||
"""Projeler sayfası - detaylı proje listesi"""
|
||
projects = Project.objects.all().select_related('customer', 'ssh_credential')
|
||
ssh_credentials = SSHCredential.objects.all()
|
||
customers = Customer.objects.filter(is_active=True).order_by('name')
|
||
ssh_logs = SSHLog.objects.all() # Log kayıtlarını al
|
||
|
||
context = {
|
||
'projects': projects,
|
||
'ssh_credentials': ssh_credentials,
|
||
'customers': customers,
|
||
'ssh_logs': ssh_logs, # Log kayıtlarını context'e ekle
|
||
}
|
||
return render(request, 'ssh_manager/projeler.html', context)
|
||
|
||
def projeler(request):
|
||
"""Projeler sayfası için wrapper - project_list'i çağırır"""
|
||
return project_list(request)
|
||
|
||
|
||
|
||
def update_all_hosts_status():
|
||
"""Tüm hostların bağlantı durumunu ve disk kullanım bilgisini güncelle"""
|
||
print("update_all_hosts_status fonksiyonu çağrıldı")
|
||
ssh_credentials = SSHCredential.objects.all()
|
||
print(f"Toplam {ssh_credentials.count()} host bulundu")
|
||
|
||
for credential in ssh_credentials:
|
||
print(f"Host kontrol ediliyor: {credential.hostname}")
|
||
ssh_manager = SSHManager(credential)
|
||
try:
|
||
# Bağlantı durumunu kontrol et
|
||
is_online = ssh_manager.check_connection()
|
||
print(f"{credential.hostname} bağlantı durumu: {is_online}")
|
||
credential.is_online = is_online
|
||
|
||
# Disk kullanım bilgisini al (sadece online ise)
|
||
if is_online:
|
||
disk_usage_info = ssh_manager.get_disk_usage()
|
||
print(f"{credential.hostname} disk bilgisi: {disk_usage_info}")
|
||
if disk_usage_info:
|
||
# Dictionary'yi string'e çevir (görüntüleme için)
|
||
credential.disk_usage = f"{disk_usage_info['used']} / {disk_usage_info['total']} ({disk_usage_info['usage_percent']}%)"
|
||
print(f"{credential.hostname} disk kullanımı kaydedildi: {credential.disk_usage}")
|
||
else:
|
||
credential.disk_usage = None
|
||
print(f"{credential.hostname} disk bilgisi alınamadı")
|
||
else:
|
||
credential.disk_usage = None
|
||
print(f"{credential.hostname} offline, disk bilgisi null")
|
||
|
||
credential.save()
|
||
print(f"{credential.hostname} veritabanına kaydedildi")
|
||
|
||
except Exception as e:
|
||
# Hata durumunda offline olarak işaretle
|
||
credential.is_online = False
|
||
credential.disk_usage = None
|
||
credential.save()
|
||
print(f"Host {credential.hostname} güncelleme hatası: {e}")
|
||
finally:
|
||
ssh_manager.close()
|
||
|
||
print("update_all_hosts_status tamamlandı")
|
||
|
||
@require_http_methods(["GET", "POST"])
|
||
def create_project(request):
|
||
if request.method == 'POST':
|
||
name = request.POST.get('name')
|
||
folder_name = request.POST.get('folder_name')
|
||
ssh_credential_id = request.POST.get('ssh_credential')
|
||
url = request.POST.get('url', '').strip()
|
||
ssh_manager = None
|
||
|
||
try:
|
||
ssh_credential = SSHCredential.objects.get(id=ssh_credential_id)
|
||
|
||
# SSH bağlantısı kur ve kontrol et
|
||
ssh_manager = SSHManager(ssh_credential)
|
||
connection_status = ssh_manager.check_connection()
|
||
|
||
if not connection_status:
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': 'SSH bağlantısı kurulamadı! Lütfen bağlantı bilgilerini kontrol edin.'
|
||
})
|
||
|
||
# Proje klasör adının benzersiz olup olmadığını kontrol et
|
||
if Project.objects.filter(folder_name=folder_name, ssh_credential=ssh_credential).exists():
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': f'"{folder_name}" klasör adı bu sunucuda zaten kullanılıyor!'
|
||
})
|
||
|
||
# Klasörün var olup olmadığını kontrol et
|
||
check_cmd = f'test -d "{ssh_credential.base_path}/{folder_name}" && echo "exists" || echo "not exists"'
|
||
stdout, stderr, status = ssh_manager.execute_command(check_cmd)
|
||
|
||
if stdout.strip() == "exists":
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': f'"{folder_name}" klasörü sunucuda zaten mevcut!'
|
||
})
|
||
|
||
# Proje oluştur
|
||
customer_id = request.POST.get('customer')
|
||
customer = None
|
||
if customer_id:
|
||
try:
|
||
customer = Customer.objects.get(id=customer_id)
|
||
except Customer.DoesNotExist:
|
||
pass
|
||
|
||
project = Project(
|
||
name=name,
|
||
folder_name=folder_name,
|
||
ssh_credential=ssh_credential,
|
||
customer=customer,
|
||
url=url if url else None
|
||
)
|
||
|
||
try:
|
||
project.full_clean()
|
||
except ValidationError as e:
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': f'Validasyon hatası: {e}'
|
||
})
|
||
|
||
# Önce projeyi kaydet
|
||
project.save()
|
||
|
||
# Klasör oluştur ve izinleri ayarla
|
||
commands = [
|
||
f'mkdir -p "{project.get_full_path()}"',
|
||
f'chown -R www-data:www-data "{project.get_full_path()}"',
|
||
f'chmod -R 755 "{project.get_full_path()}"',
|
||
]
|
||
|
||
for cmd in commands:
|
||
stdout, stderr, status = ssh_manager.execute_command(cmd)
|
||
if not status:
|
||
# Hata durumunda projeyi sil
|
||
ssh_manager.execute_command(f'rm -rf "{project.get_full_path()}"')
|
||
project.delete()
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': f'Klasör işlemleri sırasında hata: {stderr}'
|
||
})
|
||
|
||
|
||
|
||
# Log oluştur
|
||
SSHLog.objects.create(
|
||
ssh_credential=ssh_credential,
|
||
log_type='project',
|
||
command=f'Proje oluşturuldu: {name}',
|
||
output=f'Klasör: {project.get_full_path()}',
|
||
status=True
|
||
)
|
||
|
||
return JsonResponse({
|
||
'success': True,
|
||
'message': f'Proje başarıyla oluşturuldu: {project.get_full_path()}'
|
||
})
|
||
|
||
except SSHCredential.DoesNotExist:
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': 'Geçersiz SSH bağlantısı!'
|
||
})
|
||
|
||
except Exception as e:
|
||
logger.exception("Proje oluşturma hatası")
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': f'Beklenmeyen bir hata oluştu: {str(e)}'
|
||
})
|
||
|
||
finally:
|
||
if ssh_manager:
|
||
ssh_manager.close()
|
||
|
||
# GET isteği için SSH credentials listesini JSON olarak dön
|
||
ssh_credentials = SSHCredential.objects.all()
|
||
return JsonResponse({
|
||
'ssh_credentials': list(ssh_credentials.values('id', 'hostname', 'username', 'base_path'))
|
||
})
|
||
|
||
def view_logs(request, ssh_credential_id=None):
|
||
if ssh_credential_id:
|
||
# Belirli bir SSH bağlantısının loglarını göster
|
||
credential = SSHCredential.objects.get(id=ssh_credential_id)
|
||
logs = SSHLog.objects.filter(ssh_credential=credential)
|
||
context = {'credential': credential, 'logs': logs}
|
||
else:
|
||
# Tüm logları göster
|
||
logs = SSHLog.objects.all()
|
||
context = {'logs': logs}
|
||
|
||
return render(request, 'ssh_manager/view_logs.html', context)
|
||
|
||
@require_http_methods(["POST"])
|
||
def check_connection(request, project_id):
|
||
try:
|
||
project = Project.objects.get(id=project_id)
|
||
ssh_manager = SSHManager(project.ssh_credential)
|
||
|
||
if ssh_manager.check_connection():
|
||
messages.success(request, 'Bağlantı başarılı')
|
||
else:
|
||
messages.error(request, 'Bağlantı başarısız')
|
||
|
||
if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
|
||
return render(request, 'ssh_manager/messages.html')
|
||
return redirect('project_list')
|
||
|
||
except Exception as e:
|
||
messages.error(request, str(e))
|
||
if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
|
||
return render(request, 'ssh_manager/messages.html')
|
||
return redirect('project_list')
|
||
|
||
def check_folder_permissions(request):
|
||
# Klasör işlemleriyle ilgili logları getir
|
||
folder_logs = SSHLog.objects.filter(
|
||
log_type='folder'
|
||
).order_by('created_at')
|
||
|
||
# Bağlantı loglarını getir
|
||
connection_logs = SSHLog.objects.filter(
|
||
log_type='connection'
|
||
).order_by('created_at')
|
||
|
||
context = {
|
||
'folder_logs': folder_logs,
|
||
'connection_logs': connection_logs
|
||
}
|
||
|
||
return render(request, 'ssh_manager/check_permissions.html', context)
|
||
|
||
@require_http_methods(["POST"])
|
||
def upload_project_zip(request, project_id):
|
||
try:
|
||
project = get_object_or_404(Project, id=project_id)
|
||
|
||
if 'zip_file' not in request.FILES:
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': 'Dosya seçilmedi'
|
||
})
|
||
|
||
zip_file = request.FILES['zip_file']
|
||
|
||
# Dosya uzantısı kontrolü
|
||
allowed_extensions = ['.zip', '.txt']
|
||
file_extension = os.path.splitext(zip_file.name)[1].lower()
|
||
|
||
if file_extension not in allowed_extensions:
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': 'Geçersiz dosya formatı. Sadece .zip ve .txt dosyaları yüklenebilir.'
|
||
})
|
||
|
||
# SSH bağlantısı
|
||
ssh_manager = project.ssh_credential.get_manager()
|
||
|
||
try:
|
||
# Bağlantı kontrolü
|
||
if not ssh_manager.check_connection():
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': 'SSH bağlantısı kurulamadı'
|
||
})
|
||
|
||
# Dosyayı geçici olarak kaydet
|
||
fs = FileSystemStorage(location='temp_uploads')
|
||
filename = fs.save(zip_file.name, zip_file)
|
||
file_path = fs.path(filename)
|
||
|
||
try:
|
||
# SFTP ile dosyayı yükle
|
||
sftp = ssh_manager.client.open_sftp()
|
||
remote_path = f"{project.get_full_path()}/{zip_file.name}"
|
||
sftp.put(file_path, remote_path)
|
||
sftp.close()
|
||
|
||
# Zip dosyasını aç
|
||
if file_extension == '.zip':
|
||
unzip_cmd = f'cd {project.get_full_path()} && unzip -o "{zip_file.name}" && rm "{zip_file.name}"'
|
||
stdout, stderr, status = ssh_manager.execute_command(unzip_cmd)
|
||
|
||
if not status:
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': f'Zip dosyası açılamadı: {stderr}'
|
||
})
|
||
|
||
# Log oluştur
|
||
SSHLog.objects.create(
|
||
ssh_credential=project.ssh_credential,
|
||
log_type='upload',
|
||
command='Dosya Yükleme',
|
||
output=f'Dosya başarıyla yüklendi: {zip_file.name}',
|
||
status=True
|
||
)
|
||
|
||
return JsonResponse({
|
||
'success': True,
|
||
'message': 'Dosya başarıyla yüklendi'
|
||
})
|
||
|
||
finally:
|
||
# Geçici dosyayı sil
|
||
if os.path.exists(file_path):
|
||
os.remove(file_path)
|
||
|
||
finally:
|
||
ssh_manager.close()
|
||
|
||
except Exception as e:
|
||
logger.exception("Dosya yükleme hatası")
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': f'Beklenmeyen bir hata oluştu: {str(e)}'
|
||
})
|
||
|
||
@require_http_methods(["POST"])
|
||
@csrf_exempt
|
||
def delete_project(request, project_id):
|
||
try:
|
||
project = get_object_or_404(Project, id=project_id)
|
||
ssh_manager = project.ssh_credential.get_manager()
|
||
|
||
try:
|
||
# Önce proje klasörünün varlığını kontrol et
|
||
check_cmd = f'test -d "{project.get_full_path()}" && echo "exists" || echo "not exists"'
|
||
stdout, stderr, status = ssh_manager.execute_command(check_cmd)
|
||
|
||
if stdout.strip() != "exists":
|
||
project.delete()
|
||
return JsonResponse({'success': True, 'message': 'Proje veritabanından silindi (klasör zaten silinmiş)'})
|
||
|
||
# Klasör varsa silme işlemini başlat
|
||
delete_cmd = f'rm -rf "{project.get_full_path()}"'
|
||
stdout, stderr, status = ssh_manager.execute_command(delete_cmd)
|
||
|
||
if status:
|
||
project.delete()
|
||
return JsonResponse({'success': True, 'message': 'Proje başarıyla silindi'})
|
||
else:
|
||
return JsonResponse({'success': False, 'message': f'Proje silinirken hata oluştu: {stderr}'})
|
||
|
||
except Exception as e:
|
||
return JsonResponse({'success': False, 'message': f'Silme işlemi sırasında hata: {str(e)}'})
|
||
finally:
|
||
ssh_manager.close()
|
||
|
||
except Project.DoesNotExist:
|
||
return JsonResponse({'success': False, 'message': 'Proje bulunamadı'})
|
||
|
||
@require_http_methods(["POST"])
|
||
def setup_venv(request, project_id):
|
||
try:
|
||
project = get_object_or_404(Project, id=project_id)
|
||
ssh_manager = project.ssh_credential.get_manager()
|
||
|
||
logger.info(f"Setting up virtual environment for project: {project.name}")
|
||
|
||
# Virtual environment kurulumu
|
||
cmd = f'''
|
||
cd {project.get_full_path()} && \
|
||
python3 -m venv venv && \
|
||
sudo chown -R www-data:www-data venv && \
|
||
sudo chmod -R 755 venv
|
||
'''
|
||
|
||
stdout, stderr, status = ssh_manager.execute_command(cmd)
|
||
|
||
if status:
|
||
SSHLog.objects.create(
|
||
ssh_credential=project.ssh_credential,
|
||
log_type='command',
|
||
command="Virtual Environment Kurulumu",
|
||
output=f"Başarılı: {stdout}",
|
||
status=True
|
||
)
|
||
return JsonResponse({
|
||
'status': 'success',
|
||
'message': 'Virtual environment başarıyla oluşturuldu'
|
||
})
|
||
else:
|
||
error_msg = f'Virtual environment oluşturulamadı: {stderr}'
|
||
logger.error(error_msg)
|
||
SSHLog.objects.create(
|
||
ssh_credential=project.ssh_credential,
|
||
log_type='command',
|
||
command="Virtual Environment Kurulumu",
|
||
output=f"Hata: {stderr}",
|
||
status=False
|
||
)
|
||
return JsonResponse({
|
||
'status': 'error',
|
||
'message': error_msg
|
||
}, status=500)
|
||
|
||
except Exception as e:
|
||
logger.exception("Error in setup_venv")
|
||
return JsonResponse({
|
||
'status': 'error',
|
||
'message': str(e)
|
||
}, status=500)
|
||
finally:
|
||
if 'ssh_manager' in locals():
|
||
ssh_manager.close()
|
||
|
||
@require_http_methods(["GET"])
|
||
def download_requirements(request, project_id):
|
||
try:
|
||
project = get_object_or_404(Project, id=project_id)
|
||
ssh_manager = project.ssh_credential.get_manager()
|
||
|
||
# req.txt dosyasını kontrol et ve içeriğini al
|
||
check_cmd = f'test -f "{project.get_full_path()}/req.txt" && cat "{project.get_full_path()}/req.txt"'
|
||
stdout, stderr, status = ssh_manager.execute_command(check_cmd)
|
||
|
||
if status:
|
||
response = HttpResponse(stdout, content_type='text/plain')
|
||
response['Content-Disposition'] = f'attachment; filename="{project.folder_name}_req.txt"'
|
||
return response
|
||
else:
|
||
return HttpResponse('req.txt dosyası bulunamadı.', status=404)
|
||
except Exception as e:
|
||
return HttpResponse(f'Hata: {str(e)}', status=500)
|
||
finally:
|
||
if 'ssh_manager' in locals():
|
||
ssh_manager.close()
|
||
|
||
@require_http_methods(["GET"])
|
||
def check_requirements(request, project_id):
|
||
try:
|
||
project = get_object_or_404(Project, id=project_id)
|
||
ssh_manager = project.ssh_credential.get_manager()
|
||
|
||
# Tam yolu logla
|
||
full_path = project.get_full_path()
|
||
logger.info(f"Proje bilgileri:")
|
||
logger.info(f"Proje adı: {project.name}")
|
||
logger.info(f"Klasör adı: {project.folder_name}")
|
||
logger.info(f"Tam yol: {full_path}")
|
||
|
||
# Önce dosyanın varlığını kontrol et
|
||
check_cmd = f'test -f "{full_path}/req.txt" && echo "exists"'
|
||
check_stdout, check_stderr, check_status = ssh_manager.execute_command(check_cmd)
|
||
logger.info(f"Dosya kontrol komutu: {check_cmd}")
|
||
logger.info(f"Kontrol çıktısı: {check_stdout}")
|
||
|
||
if check_status and check_stdout.strip() == "exists":
|
||
# Dosya varsa içeriğini oku
|
||
cat_cmd = f'cat "{full_path}/req.txt"'
|
||
stdout, stderr, status = ssh_manager.execute_command(cat_cmd)
|
||
logger.info(f"Okuma komutu: {cat_cmd}")
|
||
logger.info(f"Okuma çıktısı: {stdout}")
|
||
logger.info(f"Okuma hatası: {stderr}")
|
||
|
||
if status and stdout.strip():
|
||
return JsonResponse({
|
||
'success': True,
|
||
'content': stdout
|
||
})
|
||
else:
|
||
error_msg = 'req.txt dosyası boş' if status else f'req.txt dosyası okunamadı: {stderr}'
|
||
logger.error(error_msg)
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': error_msg
|
||
})
|
||
else:
|
||
error_msg = 'req.txt dosyası bulunamadı'
|
||
logger.error(error_msg)
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': error_msg
|
||
})
|
||
|
||
except Exception as e:
|
||
logger.exception("req.txt kontrol hatası")
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': f'Hata: {str(e)}'
|
||
})
|
||
finally:
|
||
if 'ssh_manager' in locals():
|
||
ssh_manager.close()
|
||
|
||
@require_http_methods(["GET"])
|
||
def download_req_file(request, project_id):
|
||
try:
|
||
project = get_object_or_404(Project, id=project_id)
|
||
ssh_manager = project.ssh_credential.get_manager()
|
||
|
||
try:
|
||
# Dosya içeriğini doğrudan oku
|
||
command = f'cat "{project.get_full_path()}/req.txt"'
|
||
stdout, stderr, status = ssh_manager.execute_command(command)
|
||
|
||
if not status:
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': 'req.txt dosyası bulunamadı'
|
||
})
|
||
|
||
# Dosya içeriği varsa, indirme yanıtı oluştur
|
||
response = HttpResponse(stdout, content_type='text/plain')
|
||
response['Content-Disposition'] = f'attachment; filename="{project.folder_name}_req.txt"'
|
||
|
||
# Log oluştur
|
||
SSHLog.objects.create(
|
||
ssh_credential=project.ssh_credential,
|
||
log_type='download',
|
||
command='Requirements İndirme',
|
||
output=f'req.txt dosyası indirildi: {project.folder_name}',
|
||
status=True
|
||
)
|
||
|
||
return response
|
||
|
||
finally:
|
||
ssh_manager.close()
|
||
|
||
except Exception as e:
|
||
logger.exception("Requirements indirme hatası")
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': f'Dosya indirme hatası: {str(e)}'
|
||
})
|
||
|
||
def create_system_log(message, status=True, log_type='system', ssh_credential=None, command=None, output=None):
|
||
"""Sistem logu oluştur ve JSON olarak dön"""
|
||
log = SSHLog.objects.create(
|
||
ssh_credential=ssh_credential,
|
||
log_type=log_type,
|
||
command=command or 'Sistem',
|
||
output=output or message,
|
||
status=status
|
||
)
|
||
return {
|
||
'id': log.id,
|
||
'timestamp': log.created_at.strftime('%H:%M:%S'),
|
||
'message': message,
|
||
'command': command,
|
||
'output': output,
|
||
'status': status
|
||
}
|
||
|
||
@require_http_methods(["POST"])
|
||
def clear_logs(request):
|
||
try:
|
||
# Tüm logları sil
|
||
SSHLog.objects.all().delete()
|
||
|
||
# Log oluştur
|
||
SSHLog.objects.create(
|
||
ssh_credential=SSHCredential.objects.first(),
|
||
log_type='command',
|
||
command='Clear Logs',
|
||
output='Tüm log kayıtları temizlendi',
|
||
status=True
|
||
)
|
||
|
||
return JsonResponse({
|
||
'success': True,
|
||
'message': 'Loglar başarıyla temizlendi'
|
||
})
|
||
except Exception as e:
|
||
logger.exception("Log temizleme hatası")
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': f'Loglar temizlenirken hata oluştu: {str(e)}'
|
||
}, status=500)
|
||
|
||
@require_http_methods(["GET"])
|
||
def check_venv(request, project_id):
|
||
try:
|
||
project = get_object_or_404(Project, id=project_id)
|
||
ssh_manager = project.ssh_credential.get_manager()
|
||
|
||
# venv klasörünün varlığını kontrol et
|
||
check_cmd = f'test -d "{project.get_full_path()}/venv" && echo "exists" || echo "not exists"'
|
||
stdout, stderr, status = ssh_manager.execute_command(check_cmd)
|
||
|
||
exists = stdout.strip() == "exists"
|
||
|
||
log_data = create_system_log(
|
||
message=f'Virtual environment kontrolü: {"Mevcut" if exists else "Mevcut değil"}',
|
||
status=True,
|
||
ssh_credential=project.ssh_credential,
|
||
command='Venv Kontrolü',
|
||
output=f'Proje: {project.name}'
|
||
)
|
||
|
||
return JsonResponse({
|
||
'success': True,
|
||
'exists': exists,
|
||
'log': log_data
|
||
})
|
||
|
||
except Exception as e:
|
||
logger.exception("Venv kontrol hatası")
|
||
log_data = create_system_log(
|
||
message=f'Virtual environment kontrol hatası: {str(e)}',
|
||
status=False,
|
||
ssh_credential=project.ssh_credential,
|
||
command='Venv Kontrolü'
|
||
)
|
||
return JsonResponse({
|
||
'success': False,
|
||
'exists': False,
|
||
'log': log_data
|
||
})
|
||
finally:
|
||
if 'ssh_manager' in locals():
|
||
ssh_manager.close()
|
||
|
||
@require_http_methods(["POST"])
|
||
def install_requirements(request, project_id):
|
||
try:
|
||
project = get_object_or_404(Project, id=project_id)
|
||
ssh_manager = project.ssh_credential.get_manager()
|
||
|
||
# Venv'i aktive et ve pip install çalıştır
|
||
cmd = f'''
|
||
cd {project.get_full_path()} && \
|
||
source venv/bin/activate && \
|
||
if [ -f "req.txt" ]; then
|
||
pip install -r req.txt
|
||
else
|
||
echo "req.txt dosyası bulunamadı"
|
||
exit 1
|
||
fi
|
||
'''
|
||
|
||
stdout, stderr, status = ssh_manager.execute_command(cmd)
|
||
|
||
if status:
|
||
log_data = create_system_log(
|
||
message='Paketler başarıyla kuruldu',
|
||
status=True,
|
||
ssh_credential=project.ssh_credential,
|
||
command='Pip Install',
|
||
output=stdout
|
||
)
|
||
else:
|
||
log_data = create_system_log(
|
||
message='Paket kurulumu başarısız oldu',
|
||
status=False,
|
||
ssh_credential=project.ssh_credential,
|
||
command='Pip Install',
|
||
output=stderr
|
||
)
|
||
|
||
return JsonResponse({
|
||
'success': status,
|
||
'log': log_data
|
||
})
|
||
|
||
except Exception as e:
|
||
logger.exception("Paket kurulum hatası")
|
||
log_data = create_system_log(
|
||
message=f'Paket kurulum hatası: {str(e)}',
|
||
status=False,
|
||
ssh_credential=project.ssh_credential,
|
||
command='Pip Install'
|
||
)
|
||
return JsonResponse({
|
||
'success': False,
|
||
'log': log_data
|
||
})
|
||
finally:
|
||
if 'ssh_manager' in locals():
|
||
ssh_manager.close()
|
||
|
||
@require_http_methods(["GET"])
|
||
def check_folder_empty(request, project_id):
|
||
try:
|
||
project = get_object_or_404(Project, id=project_id)
|
||
ssh_manager = project.ssh_credential.get_manager()
|
||
|
||
# Klasördeki dosya ve klasörleri listele
|
||
cmd = f'ls -A "{project.get_full_path()}"'
|
||
stdout, stderr, status = ssh_manager.execute_command(cmd)
|
||
|
||
is_empty = not stdout.strip() # Boş string ise klasör boştur
|
||
|
||
if not is_empty:
|
||
files = stdout.strip().split('\n')
|
||
log_data = create_system_log(
|
||
message=f'Klasör içeriği kontrol edildi: {len(files)} öğe mevcut',
|
||
status=True,
|
||
ssh_credential=project.ssh_credential,
|
||
command='Klasör Kontrolü',
|
||
output=f'Mevcut dosyalar: {", ".join(files)}'
|
||
)
|
||
else:
|
||
log_data = create_system_log(
|
||
message='Klasör boş',
|
||
status=True,
|
||
ssh_credential=project.ssh_credential,
|
||
command='Klasör Kontrolü'
|
||
)
|
||
|
||
return JsonResponse({
|
||
'success': True,
|
||
'is_empty': is_empty,
|
||
'files': stdout.strip().split('\n') if not is_empty else [],
|
||
'log': log_data
|
||
})
|
||
|
||
except Exception as e:
|
||
logger.exception("Klasör kontrol hatası")
|
||
log_data = create_system_log(
|
||
message=f'Klasör kontrol hatası: {str(e)}',
|
||
status=False,
|
||
ssh_credential=project.ssh_credential,
|
||
command='Klasör Kontrolü'
|
||
)
|
||
return JsonResponse({
|
||
'success': False,
|
||
'log': log_data
|
||
})
|
||
finally:
|
||
if 'ssh_manager' in locals():
|
||
ssh_manager.close()
|
||
|
||
@login_required
|
||
def list_project_files(request, project_id):
|
||
try:
|
||
project = get_object_or_404(Project, id=project_id)
|
||
ssh_manager = SSHManager(project.ssh_credential)
|
||
|
||
if not ssh_manager.check_connection():
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': 'SSH bağlantısı kurulamadı!'
|
||
})
|
||
|
||
# Proje klasöründeki dosyaları listele
|
||
cmd = f'ls -la "{project.get_full_path()}"'
|
||
stdout, stderr, status = ssh_manager.execute_command(cmd)
|
||
|
||
if not status:
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': f'Dosya listesi alınamadı: {stderr}'
|
||
})
|
||
|
||
# ls -la çıktısını parse et
|
||
files = []
|
||
for line in stdout.splitlines()[1:]: # İlk satırı atla (toplam)
|
||
if line.strip():
|
||
parts = line.split()
|
||
if len(parts) >= 9:
|
||
permissions = parts[0]
|
||
size = parts[4]
|
||
date = ' '.join(parts[5:8])
|
||
name = ' '.join(parts[8:])
|
||
|
||
files.append({
|
||
'name': name,
|
||
'permissions': permissions,
|
||
'size': size,
|
||
'date': date
|
||
})
|
||
|
||
return JsonResponse({
|
||
'success': True,
|
||
'files': files
|
||
})
|
||
|
||
except Project.DoesNotExist:
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': 'Proje bulunamadı!'
|
||
})
|
||
except Exception as e:
|
||
logger.exception("Dosya listeleme hatası")
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': f'Beklenmeyen bir hata oluştu: {str(e)}'
|
||
})
|
||
finally:
|
||
if 'ssh_manager' in locals():
|
||
ssh_manager.close()
|
||
|
||
@login_required
|
||
def upload_project_files(request, project_id):
|
||
try:
|
||
project = get_object_or_404(Project, id=project_id)
|
||
ssh_manager = SSHManager(project.ssh_credential)
|
||
|
||
try:
|
||
success, ssh_message = ssh_manager.upload_project_zip(project, request.FILES['files'])
|
||
|
||
if success:
|
||
# Başarılı durumda log oluştur
|
||
SSHLog.objects.create(
|
||
ssh_credential=project.ssh_credential,
|
||
log_type='upload',
|
||
command='Dosya Yükleme',
|
||
output=ssh_message, # SSH'den dönen detaylı başarı mesajı
|
||
status=True
|
||
)
|
||
# Kullanıcıya genel başarı mesajı
|
||
return JsonResponse({
|
||
'success': True,
|
||
'message': 'Dosyalar başarıyla yüklendi'
|
||
})
|
||
else:
|
||
# Hata durumunda detaylı log oluştur
|
||
logger.error(ssh_message) # SSH hatasını direkt logla
|
||
SSHLog.objects.create(
|
||
ssh_credential=project.ssh_credential,
|
||
log_type='upload',
|
||
command='Dosya Yükleme',
|
||
output=ssh_message, # SSH'den dönen detaylı hata mesajı
|
||
status=False
|
||
)
|
||
# Kullanıcıya genel hata mesajı
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': 'Dosya yükleme işlemi başarısız oldu'
|
||
})
|
||
|
||
finally:
|
||
ssh_manager.close()
|
||
|
||
except Project.DoesNotExist:
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': 'Proje bulunamadı'
|
||
})
|
||
|
||
except Exception as e:
|
||
# Beklenmeyen hataları detaylı şekilde logla
|
||
logger.exception('Beklenmeyen bir hata oluştu')
|
||
SSHLog.objects.create(
|
||
ssh_credential=project.ssh_credential if 'project' in locals() else None,
|
||
log_type='upload',
|
||
command='Dosya Yükleme',
|
||
output=str(e), # Ham hata mesajı
|
||
status=False
|
||
)
|
||
# Kullanıcıya genel hata mesajı
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': 'Beklenmeyen bir hata oluştu'
|
||
})
|
||
|
||
@require_http_methods(["POST"])
|
||
def get_latest_logs(request):
|
||
logs = SSHLog.objects.all().order_by('-created_at')[:50] # Son 50 log
|
||
log_data = [{
|
||
'created_at': log.created_at.strftime('%d.%m.%Y %H:%M:%S'),
|
||
'log_type_display': log.get_log_type_display(),
|
||
'command': log.command,
|
||
'output': log.output,
|
||
'status': log.status
|
||
} for log in logs]
|
||
|
||
return JsonResponse({'logs': log_data})
|
||
|
||
@require_http_methods(["POST"])
|
||
def restart_supervisor(request, project_id):
|
||
try:
|
||
project = get_object_or_404(Project, id=project_id)
|
||
ssh_manager = project.ssh_credential.get_manager()
|
||
|
||
try:
|
||
# Supervisor'ı yeniden başlat
|
||
cmd = f'sudo supervisorctl restart {project.folder_name}'
|
||
stdout, stderr, status = ssh_manager.execute_command(cmd)
|
||
|
||
if status:
|
||
log_data = create_system_log(
|
||
message='Supervisor başarıyla yeniden başlatıldı',
|
||
status=True,
|
||
ssh_credential=project.ssh_credential,
|
||
command='Supervisor Restart',
|
||
output=stdout
|
||
)
|
||
return JsonResponse({
|
||
'success': True,
|
||
'message': 'Uygulama başarıyla yeniden başlatıldı',
|
||
'log': log_data
|
||
})
|
||
else:
|
||
log_data = create_system_log(
|
||
message='Supervisor yeniden başlatılamadı',
|
||
status=False,
|
||
ssh_credential=project.ssh_credential,
|
||
command='Supervisor Restart',
|
||
output=stderr
|
||
)
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': 'Uygulama yeniden başlatılamadı',
|
||
'log': log_data
|
||
})
|
||
|
||
except Exception as e:
|
||
logger.exception("Supervisor restart hatası")
|
||
log_data = create_system_log(
|
||
message=f'Supervisor restart hatası: {str(e)}',
|
||
status=False,
|
||
ssh_credential=project.ssh_credential,
|
||
command='Supervisor Restart'
|
||
)
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': str(e),
|
||
'log': log_data
|
||
})
|
||
finally:
|
||
ssh_manager.close()
|
||
|
||
except Project.DoesNotExist:
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': 'Proje bulunamadı'
|
||
})
|
||
|
||
@require_http_methods(["POST"])
|
||
def update_requirements(request, project_id):
|
||
try:
|
||
project = get_object_or_404(Project, id=project_id)
|
||
ssh_manager = project.ssh_credential.get_manager()
|
||
|
||
# JSON verilerini al
|
||
data = json.loads(request.body)
|
||
new_content = data.get('content', '')
|
||
|
||
# Yeni içeriği req.txt dosyasına yaz
|
||
write_cmd = f'echo "{new_content}" > "{project.get_full_path()}/req.txt"'
|
||
stdout, stderr, status = ssh_manager.execute_command(write_cmd)
|
||
|
||
if status:
|
||
log_data = create_system_log(
|
||
message='Requirements içeriği güncellendi',
|
||
status=True,
|
||
ssh_credential=project.ssh_credential,
|
||
command='Requirements Güncelleme',
|
||
output=stdout
|
||
)
|
||
return JsonResponse({
|
||
'success': True,
|
||
'message': 'Requirements içeriği başarıyla güncellendi',
|
||
'log': log_data
|
||
})
|
||
else:
|
||
log_data = create_system_log(
|
||
message='Requirements güncellenirken hata oluştu',
|
||
status=False,
|
||
ssh_credential=project.ssh_credential,
|
||
command='Requirements Güncelleme',
|
||
output=stderr
|
||
)
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': f'Requirements güncellenirken hata oluştu: {stderr}',
|
||
'log': log_data
|
||
})
|
||
|
||
except Exception as e:
|
||
logger.exception("Requirements güncelleme hatası")
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': f'Hata: {str(e)}'
|
||
})
|
||
finally:
|
||
if 'ssh_manager' in locals():
|
||
ssh_manager.close()
|
||
|
||
@require_http_methods(["POST"])
|
||
def delete_requirement_line(request, project_id):
|
||
try:
|
||
project = get_object_or_404(Project, id=project_id)
|
||
ssh_manager = project.ssh_credential.get_manager()
|
||
|
||
# JSON verilerini al
|
||
data = json.loads(request.body)
|
||
line_index = int(data.get('line_index', -1)) # int'e çevir
|
||
|
||
# Mevcut içeriği oku
|
||
read_cmd = f'cat "{project.get_full_path()}/req.txt"'
|
||
stdout, stderr, status = ssh_manager.execute_command(read_cmd)
|
||
|
||
if not status:
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': 'Requirements dosyası okunamadı'
|
||
})
|
||
|
||
# Satırları ayır ve belirtilen satırı sil
|
||
lines = [line for line in stdout.strip().split('\n') if line.strip()] # Boş satırları filtrele
|
||
|
||
if 0 <= line_index < len(lines):
|
||
deleted_line = lines.pop(line_index)
|
||
new_content = '\n'.join(lines)
|
||
|
||
# Yeni içeriği dosyaya yaz
|
||
write_cmd = f"echo '{new_content}' > '{project.get_full_path()}/req.txt'"
|
||
stdout, stderr, status = ssh_manager.execute_command(write_cmd)
|
||
|
||
if status:
|
||
log_data = create_system_log(
|
||
message=f'Requirements satırı silindi: {deleted_line}',
|
||
status=True,
|
||
ssh_credential=project.ssh_credential,
|
||
command='Requirements Satır Silme',
|
||
output=stdout
|
||
)
|
||
return JsonResponse({
|
||
'success': True,
|
||
'message': 'Satır başarıyla silindi',
|
||
'content': new_content,
|
||
'log': log_data
|
||
})
|
||
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': 'Satır silinemedi'
|
||
})
|
||
|
||
except Exception as e:
|
||
logger.exception("Requirements satır silme hatası")
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': f'Hata: {str(e)}'
|
||
})
|
||
finally:
|
||
if 'ssh_manager' in locals():
|
||
ssh_manager.close()
|
||
|
||
@require_http_methods(["POST"])
|
||
def refresh_project(request, project_id):
|
||
ssh_manager = None
|
||
try:
|
||
project = get_object_or_404(Project, id=project_id)
|
||
ssh_manager = project.ssh_credential.get_manager()
|
||
|
||
# Proje klasörünü kontrol et
|
||
project_path = project.get_full_path()
|
||
|
||
# Disk kullanımını hesapla (du komutu ile)
|
||
du_cmd = f"du -sh {project_path}"
|
||
stdout, stderr, status = ssh_manager.execute_command(du_cmd)
|
||
|
||
if status:
|
||
# du çıktısını parse et (örn: "156M /path/to/folder")
|
||
disk_usage = stdout.split()[0]
|
||
project.disk_usage = disk_usage
|
||
project.save()
|
||
|
||
# Requirements dosyasını kontrol et (req.txt)
|
||
stdout, stderr, status = ssh_manager.execute_command(f"ls {project_path}/req.txt")
|
||
has_requirements = status
|
||
|
||
# Requirements içeriğini al
|
||
if has_requirements:
|
||
stdout, stderr, status = ssh_manager.execute_command(f"cat {project_path}/req.txt")
|
||
req_content = stdout if status else ""
|
||
else:
|
||
req_content = ""
|
||
|
||
# Log oluştur
|
||
log_data = create_system_log(
|
||
message='Proje bilgileri güncellendi',
|
||
status=True,
|
||
ssh_credential=project.ssh_credential,
|
||
command='Proje Güncelleme',
|
||
output=f"Requirements durumu: {'Mevcut' if has_requirements else 'Mevcut değil'}"
|
||
)
|
||
|
||
return JsonResponse({
|
||
'success': True,
|
||
'project_info': {
|
||
'base_path': project.ssh_credential.base_path,
|
||
'folder_name': project.folder_name,
|
||
'disk_usage': project.disk_usage or '0B'
|
||
},
|
||
'has_requirements': has_requirements,
|
||
'requirements_content': req_content,
|
||
'message': 'Proje başarıyla güncellendi',
|
||
'log': log_data
|
||
})
|
||
|
||
except Project.DoesNotExist:
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': 'Proje bulunamadı'
|
||
}, status=404)
|
||
except Exception as e:
|
||
logger.exception("Proje güncelleme hatası")
|
||
log_data = create_system_log(
|
||
message=f'Proje güncellenirken hata oluştu: {str(e)}',
|
||
status=False,
|
||
ssh_credential=project.ssh_credential if 'project' in locals() else None,
|
||
command='Proje Güncelleme'
|
||
)
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': str(e),
|
||
'log': log_data
|
||
}, status=500)
|
||
finally:
|
||
if ssh_manager:
|
||
ssh_manager.close()
|
||
|
||
# @require_http_methods(["POST"])
|
||
# def backup_projects(request):
|
||
# logger.info("====== BACKUP İŞLEMİ BAŞLIYOR ======")
|
||
#
|
||
# try:
|
||
# ssh_credential = SSHCredential.objects.first()
|
||
# if not ssh_credential:
|
||
# raise ValueError("SSH bağlantısı bulunamadı")
|
||
#
|
||
# # Başlangıç logu
|
||
# SSHLog.objects.create(
|
||
# ssh_credential=ssh_credential,
|
||
# log_type='backup',
|
||
# command='Backup İşlemi',
|
||
# output='Yedekleme işlemi başlatıldı',
|
||
# status=True
|
||
# )
|
||
#
|
||
# # Google Drive bağlantı logu
|
||
# SSHLog.objects.create(
|
||
# ssh_credential=ssh_credential,
|
||
# log_type='backup',
|
||
# command='Google Drive Bağlantısı',
|
||
# output='Google Drive API bağlantısı kuruluyor...',
|
||
# status=True
|
||
# )
|
||
#
|
||
# credentials = service_account.Credentials.from_service_account_info(
|
||
# settings.GOOGLE_DRIVE_CREDENTIALS,
|
||
# scopes=['https://www.googleapis.com/auth/drive.file']
|
||
# )
|
||
# drive_service = build('drive', 'v3', credentials=credentials)
|
||
#
|
||
# SSHLog.objects.create(
|
||
# ssh_credential=ssh_credential,
|
||
# log_type='backup',
|
||
# command='Google Drive Bağlantısı',
|
||
# output='Google Drive API bağlantısı başarıyla kuruldu',
|
||
# status=True
|
||
# )
|
||
#
|
||
# ssh_manager = ssh_credential.get_manager()
|
||
#
|
||
# try:
|
||
# for project in Project.objects.all():
|
||
# # Proje yedekleme başlangıç logu
|
||
# SSHLog.objects.create(
|
||
# ssh_credential=ssh_credential,
|
||
# log_type='backup',
|
||
# command=f'Proje: {project.name}',
|
||
# output=f'{project.name} projesi yedekleme işlemi başladı',
|
||
# status=True
|
||
# )
|
||
#
|
||
# backup_name = f'{project.folder_name}_{datetime.now().strftime("%Y%m%d_%H%M%S")}.zip'
|
||
# project_path = project.get_full_path()
|
||
#
|
||
# # Zip işlemi
|
||
# zip_cmd = f'''
|
||
# cd {project_path}/.. && \
|
||
# zip -9 -r "{project.folder_name}.zip" "{project.folder_name}" && \
|
||
# mv "{project.folder_name}.zip" "/tmp/{backup_name}"
|
||
# '''
|
||
# logger.info(f"Zip komutu çalıştırılıyor: {zip_cmd}")
|
||
#
|
||
# stdout, stderr, status = ssh_manager.execute_command(zip_cmd)
|
||
#
|
||
# if not status:
|
||
# error_msg = f"{project.name} için zip oluşturma hatası:\nStdout: {stdout}\nStderr: {stderr}"
|
||
# SSHLog.objects.create(
|
||
# ssh_credential=ssh_credential,
|
||
# log_type='backup',
|
||
# command=f'Zip Hatası: {project.name}',
|
||
# output=error_msg,
|
||
# status=False
|
||
# )
|
||
# continue
|
||
#
|
||
# # Zip dosyası boyutunu ve başarı durumunu logla
|
||
# SSHLog.objects.create(
|
||
# ssh_credential=ssh_credential,
|
||
# log_type='backup',
|
||
# command=f'Zip: {project.name}',
|
||
# output=f'{project.name} projesi için zip dosyası oluşturuldu\n{stdout}',
|
||
# status=True
|
||
# )
|
||
#
|
||
# # Dosya tipini kontrol et
|
||
# check_cmd = f'file "/tmp/{backup_name}"'
|
||
# stdout, stderr, status = ssh_manager.execute_command(check_cmd)
|
||
# logger.info(f"Dosya tipi kontrolü: {stdout}")
|
||
#
|
||
# # Dosya boyutunu kontrol et
|
||
# size_cmd = f'ls -lh "/tmp/{backup_name}"'
|
||
# size_out, size_err, size_status = ssh_manager.execute_command(size_cmd)
|
||
# logger.info(f"Dosya boyutu: {size_out}")
|
||
#
|
||
# if not status or 'Zip archive data' not in stdout:
|
||
# error_msg = f"Oluşturulan dosya bir zip arşivi değil: {stdout}"
|
||
# logger.error(error_msg)
|
||
# SSHLog.objects.create(
|
||
# ssh_credential=ssh_credential,
|
||
# log_type='backup',
|
||
# command=f'Kontrol: {project.name}',
|
||
# output=error_msg,
|
||
# status=False
|
||
# )
|
||
# continue
|
||
#
|
||
# # Google Drive yükleme işlemi...
|
||
# # ... (mevcut Drive yükleme kodu devam eder)
|
||
#
|
||
# # Tamamlanma logu
|
||
# SSHLog.objects.create(
|
||
# ssh_credential=ssh_credential,
|
||
# log_type='backup',
|
||
# command='Backup İşlemi',
|
||
# output='Tüm projelerin yedekleme işlemi başarıyla tamamlandı',
|
||
# status=True
|
||
# )
|
||
#
|
||
# return JsonResponse({
|
||
# 'success': True,
|
||
# 'message': 'Yedekleme işlemi tamamlandı!'
|
||
# })
|
||
#
|
||
# finally:
|
||
# ssh_manager.close()
|
||
#
|
||
# except Exception as e:
|
||
# error_msg = f"Yedekleme sırasında hata oluştu: {str(e)}"
|
||
# if 'ssh_credential' in locals():
|
||
# SSHLog.objects.create(
|
||
# ssh_credential=ssh_credential,
|
||
# log_type='backup',
|
||
# command='Backup Hatası',
|
||
# output=error_msg,
|
||
# status=False
|
||
# )
|
||
# return JsonResponse({
|
||
# 'success': False,
|
||
# 'message': error_msg
|
||
# })
|
||
|
||
@require_http_methods(["POST"])
|
||
def backup_project(request, project_id):
|
||
import traceback
|
||
import sys
|
||
import platform
|
||
import tempfile
|
||
|
||
# Log system information
|
||
logger.info(f"===== BACKUP DEBUG INFO =====")
|
||
logger.info(f"Backup request for project ID: {project_id}")
|
||
logger.info(f"Platform: {platform.system()} {platform.release()}")
|
||
logger.info(f"Python version: {platform.python_version()}")
|
||
logger.info(f"Temp directory: {tempfile.gettempdir()}")
|
||
logger.info(f"Working directory: {os.getcwd()}")
|
||
|
||
try:
|
||
logger.info(f"Getting project with ID: {project_id}")
|
||
project = get_object_or_404(Project, id=project_id)
|
||
|
||
folder_name = project.folder_name
|
||
# Path normalization for Linux/Windows compatibility
|
||
base_path = project.ssh_credential.base_path or ""
|
||
base_path = base_path.rstrip('/')
|
||
calisma_dizini = f"{base_path}/{folder_name}" if base_path else folder_name
|
||
|
||
logger.info(f"Project: {project.name}, Folder: {folder_name}, Path: {calisma_dizini}")
|
||
|
||
if not folder_name:
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': 'Klasör adı bulunamadı'
|
||
})
|
||
|
||
try:
|
||
# SSH bağlantısı oluştur ve hata ayıklama bilgisi ekle
|
||
logger.info(f"Establishing SSH connection to {project.ssh_credential}")
|
||
try:
|
||
ssh_manager = project.ssh_credential.get_manager()
|
||
logger.info(f"SSH connection established successfully")
|
||
except Exception as ssh_err:
|
||
logger.error(f"SSH connection error: {str(ssh_err)}")
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': f'SSH bağlantı hatası: {str(ssh_err)}'
|
||
})
|
||
|
||
# SSH üzerinde basit bir test yap
|
||
logger.info(f"Testing basic SSH functionality")
|
||
test_cmd = "echo 'SSH_TEST_OK'"
|
||
test_stdout, test_stderr, test_status = ssh_manager.execute_command(test_cmd)
|
||
logger.info(f"SSH test result: status={test_status}, output={test_stdout.strip()}")
|
||
|
||
if not test_status:
|
||
logger.error(f"SSH basic test failed: {test_stderr}")
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': f'SSH temel fonksiyonalite testi başarısız: {test_stderr}'
|
||
})
|
||
|
||
# Özel karakterleri escape et
|
||
safe_path = calisma_dizini.replace('"', '\\"')
|
||
logger.info(f"Checking directory existence: {safe_path}")
|
||
|
||
# Klasörün varlığını kontrol et
|
||
check_cmd = f'test -d "{safe_path}" && echo "exists"'
|
||
stdout, stderr, status = ssh_manager.execute_command(check_cmd)
|
||
logger.info(f"Directory check result: status={status}, output={stdout.strip()}, error={stderr.strip()}")
|
||
|
||
if not status or stdout.strip() != "exists":
|
||
# Eğer klasör yoksa üst dizini listele (debug için)
|
||
parent_dir = os.path.dirname(safe_path)
|
||
if parent_dir:
|
||
logger.info(f"Source directory not found, listing parent dir: {parent_dir}")
|
||
list_cmd = f'ls -la "{parent_dir}"'
|
||
list_stdout, list_stderr, list_status = ssh_manager.execute_command(list_cmd)
|
||
logger.info(f"Parent directory contents: {list_stdout}")
|
||
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': f'Yedeklenecek klasör bulunamadı: {calisma_dizini}'
|
||
})
|
||
|
||
# Backup kaydını oluştur (başlangıç)
|
||
backup_record = Backup.objects.create(
|
||
project=project,
|
||
backup_type='manual',
|
||
status='running',
|
||
notes=f'Manuel yedekleme başlatıldı: {calisma_dizini}'
|
||
)
|
||
|
||
# Backup işlemini başlat
|
||
logger.info(f"Starting backup job: folder={folder_name}, path={calisma_dizini}, project_id={project_id}")
|
||
|
||
try:
|
||
result = job(folder_name, calisma_dizini, project_id)
|
||
logger.info(f"Backup job result: {result}")
|
||
except Exception as backup_err:
|
||
logger.error(f"Exception during backup job: {str(backup_err)}")
|
||
logger.error(f"Traceback: {''.join(traceback.format_exception(*sys.exc_info()))}")
|
||
|
||
# Backup kaydını güncelle
|
||
backup_record.status = 'failed'
|
||
backup_record.end_time = timezone.now()
|
||
backup_record.error_message = f"Uygulama hatası: {str(backup_err)}"
|
||
backup_record.save()
|
||
|
||
raise Exception(f"Yedekleme işlemi sırasında hata: {str(backup_err)}")
|
||
|
||
if not result.get('success'):
|
||
error_msg = result.get('message', 'Backup işlemi başarısız oldu')
|
||
logger.error(f"Backup job failed: {error_msg}")
|
||
|
||
# Backup kaydını başarısız olarak güncelle
|
||
backup_record.status = 'failed'
|
||
backup_record.end_time = timezone.now()
|
||
backup_record.error_message = error_msg
|
||
backup_record.save()
|
||
|
||
raise Exception(error_msg)
|
||
|
||
# Backup başarılı - kaydı güncelle
|
||
backup_record.status = 'completed'
|
||
backup_record.end_time = timezone.now()
|
||
backup_record.notes = f'Yedekleme başarıyla tamamlandı: {calisma_dizini}'
|
||
|
||
# Backup detaylarını ekle (eğer result'ta varsa)
|
||
if result.get('file_path'):
|
||
backup_record.file_path = result.get('file_path')
|
||
if result.get('file_size'):
|
||
# Sayı olduğundan emin ol
|
||
try:
|
||
file_size = int(result.get('file_size'))
|
||
backup_record.file_size = file_size # Integer olarak sakla (BigIntegerField için uygun)
|
||
except (ValueError, TypeError):
|
||
# Sayıya çevrilemiyorsa string olarak sakla
|
||
try:
|
||
# Sayı formatındaki stringleri temizle ve dönüştür
|
||
file_size_str = str(result.get('file_size')).strip()
|
||
file_size_cleaned = ''.join(c for c in file_size_str if c.isdigit())
|
||
if file_size_cleaned:
|
||
backup_record.file_size = int(file_size_cleaned)
|
||
else:
|
||
backup_record.file_size = 0
|
||
except:
|
||
backup_record.file_size = 0
|
||
|
||
backup_record.save()
|
||
|
||
# Backup tarihini güncelle
|
||
project.last_backup = timezone.now()
|
||
project.save()
|
||
|
||
# Log oluştur
|
||
SSHLog.objects.create(
|
||
ssh_credential=project.ssh_credential,
|
||
log_type='backup',
|
||
command=f'Backup: {folder_name}',
|
||
output=f'Backup başarıyla tamamlandı. Dizin: {calisma_dizini}',
|
||
status=True
|
||
)
|
||
|
||
return JsonResponse({
|
||
'success': True,
|
||
'message': 'Yedekleme işlemi başarıyla tamamlandı'
|
||
})
|
||
|
||
except Exception as e:
|
||
# Get full exception details
|
||
exc_type, exc_value, exc_traceback = sys.exc_info()
|
||
error_details = ''.join(traceback.format_exception(exc_type, exc_value, exc_traceback))
|
||
|
||
error_msg = str(e)
|
||
logger.error(f"Exception in backup process: {error_msg}")
|
||
logger.error(f"Detailed traceback:\n{error_details}")
|
||
|
||
if 'NoSuchBucket' in error_msg:
|
||
error_msg = 'Backup bucket\'ı bulunamadı. Sistem yöneticinize başvurun.'
|
||
|
||
# Eğer backup kaydı oluşturulduysa ama başarısız olduysa güncelle
|
||
if 'backup_record' in locals():
|
||
backup_record.status = 'failed'
|
||
backup_record.end_time = timezone.now()
|
||
backup_record.error_message = f"{error_msg}\n\nTeknik detaylar: {error_details[:500]}..."
|
||
backup_record.save()
|
||
|
||
# Hata logu oluştur
|
||
SSHLog.objects.create(
|
||
ssh_credential=project.ssh_credential,
|
||
log_type='backup',
|
||
command=f'Backup Error: {folder_name}',
|
||
output=f'Hata: {error_msg}',
|
||
status=False
|
||
)
|
||
|
||
logger.exception(f"Backup error for project {project_id}")
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': f'Yedekleme işlemi başarısız: {error_msg}'
|
||
})
|
||
|
||
except Project.DoesNotExist:
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': 'Proje bulunamadı'
|
||
})
|
||
finally:
|
||
if 'ssh_manager' in locals():
|
||
ssh_manager.close()
|
||
|
||
def get_project_details(request, project_id):
|
||
try:
|
||
project = get_object_or_404(Project, id=project_id)
|
||
data = {
|
||
'success': True,
|
||
'project': {
|
||
'name': project.name,
|
||
'folder_name': project.folder_name,
|
||
'url': project.url,
|
||
'ssh_credential_id': project.ssh_credential.id if project.ssh_credential else '',
|
||
'customer_id': project.customer.id if project.customer else '',
|
||
'last_backup': project.last_backup.strftime('%d.%m.%Y %H:%M') if project.last_backup else None,
|
||
'disk_usage': project.disk_usage or '0B',
|
||
'host_renewal_date': project.host_renewal_date.strftime('%Y-%m-%d') if project.host_renewal_date else None,
|
||
}
|
||
}
|
||
return JsonResponse(data)
|
||
except Exception as e:
|
||
return JsonResponse({'success': False, 'message': 'Proje detayları alınırken bir hata oluştu.'})
|
||
|
||
@require_http_methods(["POST"])
|
||
def delete_host(request, host_id):
|
||
try:
|
||
host = SSHCredential.objects.get(id=host_id)
|
||
host.delete()
|
||
return JsonResponse({'success': True, 'message': 'Host başarıyla silindi'})
|
||
except SSHCredential.DoesNotExist:
|
||
return JsonResponse({'success': False, 'message': 'Host bulunamadı'})
|
||
except Exception as e:
|
||
return JsonResponse({'success': False, 'message': 'Host silinirken bir hata oluştu'})
|
||
|
||
@require_http_methods(["POST"])
|
||
def update_host(request, host_id):
|
||
try:
|
||
host = SSHCredential.objects.get(id=host_id)
|
||
host.hostname = request.POST.get('hostname')
|
||
host.username = request.POST.get('username')
|
||
password = request.POST.get('password')
|
||
if password:
|
||
host.password = password
|
||
host.port = request.POST.get('port')
|
||
host.base_path = request.POST.get('base_path')
|
||
host.full_clean()
|
||
host.save()
|
||
return JsonResponse({'success': True, 'message': 'Host başarıyla güncellendi'})
|
||
except SSHCredential.DoesNotExist:
|
||
return JsonResponse({'success': False, 'message': 'Host bulunamadı'})
|
||
except ValidationError as e:
|
||
return JsonResponse({'success': False, 'message': str(e)})
|
||
except Exception as e:
|
||
return JsonResponse({'success': False, 'message': 'Host güncellenirken bir hata oluştu'})
|
||
|
||
@require_http_methods(["GET"])
|
||
def project_backup_logs(request, project_id):
|
||
try:
|
||
project = get_object_or_404(Project, id=project_id)
|
||
# Hem backup hem de site kontrol loglarını getir
|
||
logs = SSHLog.objects.filter(
|
||
ssh_credential=project.ssh_credential,
|
||
).filter(
|
||
models.Q(log_type='backup', command__icontains=project.folder_name) |
|
||
models.Q(log_type='command', command__icontains=project.name)
|
||
).order_by('-created_at') # En yeni önce
|
||
|
||
log_data = [
|
||
{
|
||
'created_at': log.created_at.strftime('%d.%m.%Y %H:%M:%S'),
|
||
'command': log.command,
|
||
'output': log.output,
|
||
'status': log.status,
|
||
'log_type': log.log_type
|
||
}
|
||
for log in logs
|
||
]
|
||
return JsonResponse({'success': True, 'logs': log_data})
|
||
except Exception as e:
|
||
return JsonResponse({'success': False, 'message': str(e)})
|
||
|
||
@require_http_methods(["POST"])
|
||
def update_project(request, project_id):
|
||
try:
|
||
project = Project.objects.get(id=project_id)
|
||
|
||
project.name = request.POST.get('name')
|
||
project.folder_name = request.POST.get('folder_name')
|
||
project.url = request.POST.get('url', '')
|
||
|
||
# SSH Credential güncelleme
|
||
ssh_credential_id = request.POST.get('ssh_credential')
|
||
if ssh_credential_id:
|
||
try:
|
||
ssh_credential = SSHCredential.objects.get(id=ssh_credential_id)
|
||
project.ssh_credential = ssh_credential
|
||
except SSHCredential.DoesNotExist:
|
||
pass
|
||
|
||
# Customer güncelleme
|
||
customer_id = request.POST.get('customer')
|
||
if customer_id:
|
||
try:
|
||
customer = Customer.objects.get(id=customer_id)
|
||
project.customer = customer
|
||
except Customer.DoesNotExist:
|
||
pass
|
||
else:
|
||
project.customer = None
|
||
|
||
# Model validation
|
||
project.full_clean()
|
||
project.save()
|
||
|
||
return JsonResponse({
|
||
'success': True,
|
||
'message': 'Proje başarıyla güncellendi'
|
||
})
|
||
|
||
except Project.DoesNotExist:
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': 'Proje bulunamadı'
|
||
}, status=404)
|
||
|
||
except ValidationError as e:
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': str(e)
|
||
}, status=400)
|
||
|
||
except Exception as e:
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': 'Proje güncellenirken bir hata oluştu'
|
||
}, status=500)
|
||
|
||
@require_http_methods(["POST"])
|
||
def clear_project_logs(request, project_id):
|
||
"""Belirtilen projenin tüm loglarını sil"""
|
||
try:
|
||
project = get_object_or_404(Project, id=project_id)
|
||
|
||
# Bu projeye ait tüm logları sil - hem backup hem de site kontrol logları
|
||
deleted_count = SSHLog.objects.filter(
|
||
ssh_credential=project.ssh_credential
|
||
).filter(
|
||
# Backup logları veya site kontrol logları
|
||
Q(log_type='backup', command__icontains=project.folder_name) |
|
||
Q(log_type='command', command__icontains=project.name)
|
||
).delete()[0]
|
||
|
||
return JsonResponse({
|
||
'success': True,
|
||
'message': f'{deleted_count} log kaydı silindi',
|
||
'deleted_count': deleted_count
|
||
})
|
||
|
||
except Exception as e:
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': f'Log silme hatası: {str(e)}'
|
||
}, status=500)
|
||
|
||
@require_http_methods(["POST"])
|
||
def check_site_status_view(request, project_id):
|
||
"""Tek projenin site durumunu kontrol et"""
|
||
try:
|
||
project = get_object_or_404(Project, id=project_id)
|
||
|
||
from .utils import check_site_status, check_disk_usage
|
||
from .models import SSHLog
|
||
|
||
# Site kontrol işlemini başlat ve log kaydı yap
|
||
log_entry = SSHLog.objects.create(
|
||
ssh_credential=project.ssh_credential,
|
||
log_type='command',
|
||
command=f"Site kontrol: {project.url} (Proje: {project.name})",
|
||
output="Site kontrol işlemi başlatıldı...",
|
||
status=False # Başlangıçta False, sonra güncellenecek
|
||
)
|
||
|
||
try:
|
||
# 1. Site durumunu kontrol et (meta key doğrulaması ile)
|
||
site_status, site_message = check_site_status(project)
|
||
|
||
# 2. Disk kullanımını kontrol et (ayrı bir işlem olarak)
|
||
disk_status, disk_message = check_disk_usage(project)
|
||
|
||
# Sonuçları birleştir
|
||
combined_message = f"Site Kontrolü: {site_message}\nDisk Kontrolü: {disk_message}"
|
||
|
||
# Log kaydını güncelle
|
||
log_entry.output = combined_message
|
||
log_entry.status = site_status # Site durumuna göre log durumunu belirle
|
||
log_entry.save()
|
||
|
||
# Host bağlantı durumunu güncelle
|
||
if project.ssh_credential:
|
||
ssh_manager = SSHManager(project.ssh_credential)
|
||
try:
|
||
# Bağlantı durumunu kontrol et
|
||
is_online = ssh_manager.check_connection()
|
||
project.ssh_credential.is_online = is_online
|
||
project.ssh_credential.save()
|
||
except Exception as e:
|
||
# Hata durumunda offline olarak işaretle
|
||
project.ssh_credential.is_online = False
|
||
project.ssh_credential.save()
|
||
print(f"Host bağlantı durumu güncelleme hatası: {e}")
|
||
finally:
|
||
ssh_manager.close()
|
||
|
||
return JsonResponse({
|
||
'success': True,
|
||
'status': site_status, # Site durumunu döndür
|
||
'message': combined_message,
|
||
'site_message': site_message,
|
||
'disk_message': disk_message,
|
||
'is_active': project.is_site_active,
|
||
'disk_usage': project.disk_usage,
|
||
'last_check': project.last_site_check.strftime('%d.%m.%Y %H:%M') if project.last_site_check else None
|
||
})
|
||
|
||
except Exception as e:
|
||
# Hata durumunda log kaydını güncelle
|
||
log_entry.output = f"Kontrol hatası: {str(e)}"
|
||
log_entry.status = False
|
||
log_entry.save()
|
||
raise e
|
||
|
||
except Exception as e:
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': f'Kontrol hatası: {str(e)}'
|
||
}, status=500)
|
||
|
||
def check_all_sites_view(request):
|
||
"""Tüm projelerin site durumunu kontrol et ve sonuçları döndür"""
|
||
try:
|
||
from .utils import check_all_sites
|
||
|
||
# Tüm siteleri kontrol et
|
||
results = check_all_sites()
|
||
|
||
# Sonuçları JSON formatına dönüştür
|
||
data = {
|
||
'success': True,
|
||
'results': [
|
||
{
|
||
'project_id': result['project'].id,
|
||
'project_name': result['project'].name,
|
||
'url': result['project'].url,
|
||
'status': result['status'],
|
||
'site_message': result['site_message'],
|
||
'disk_status': result['disk_status'],
|
||
'disk_message': result['disk_message'],
|
||
'combined_message': result['combined_message']
|
||
} for result in results
|
||
]
|
||
}
|
||
|
||
return JsonResponse(data)
|
||
except Exception as e:
|
||
return JsonResponse({'success': False, 'message': f'Tüm siteleri kontrol ederken bir hata oluştu: {str(e)}'})
|
||
|
||
@require_http_methods(["GET"])
|
||
def get_domain_expiration(request):
|
||
url = request.GET.get("url")
|
||
|
||
# Basit console output ekleyelim
|
||
print(f"=== Domain expiration request başladı ===")
|
||
print(f"URL: {url}")
|
||
print(f"WHOIS_TOOLS_AVAILABLE: {WHOIS_TOOLS_AVAILABLE}")
|
||
|
||
if not url:
|
||
print("URL parametresi eksik")
|
||
return JsonResponse({"error": "URL parametresi eksik."}, status=400)
|
||
|
||
try:
|
||
if not WHOIS_TOOLS_AVAILABLE:
|
||
print("WHOIS tools modülü mevcut değil")
|
||
return JsonResponse({
|
||
"error": "WHOIS servis şu anda kullanılamıyor.",
|
||
"debug": "WHOIS_TOOLS_AVAILABLE = False"
|
||
}, status=503)
|
||
|
||
print("WHOIS tools import test başlıyor...")
|
||
|
||
# Test amaçlı import kontrolü
|
||
try:
|
||
from utils.whois_tools import test_whois_function
|
||
test_result = test_whois_function()
|
||
print(f"Test fonksiyonu sonucu: {test_result}")
|
||
except Exception as test_e:
|
||
print(f"Test fonksiyonu import hatası: {test_e}")
|
||
return JsonResponse({
|
||
"error": f"Test hatası: {str(test_e)}",
|
||
"debug": f"Import error: {test_e}"
|
||
}, status=500)
|
||
|
||
print("get_domain_expiration_date çağrılıyor...")
|
||
expiration_date = get_domain_expiration_date(url)
|
||
print(f"get_domain_expiration_date sonucu: {expiration_date}")
|
||
|
||
if expiration_date:
|
||
print(f"Başarılı sonuç döndürülüyor: {expiration_date}")
|
||
return JsonResponse({"domain_expiration": expiration_date})
|
||
else:
|
||
print("Expiration bilgisi None döndü")
|
||
return JsonResponse({"error": "Expiration bilgisi alınamadı."}, status=500)
|
||
|
||
except Exception as e:
|
||
print(f"=== GENEL HATA ===")
|
||
print(f"Hata: {str(e)}")
|
||
print(f"Hata tipi: {type(e)}")
|
||
|
||
import traceback
|
||
print(f"Traceback:")
|
||
traceback.print_exc()
|
||
|
||
return JsonResponse({
|
||
"error": f"Domain sorgusu sırasında hata oluştu: {str(e)}",
|
||
"debug": f"Exception type: {type(e).__name__}"
|
||
}, status=500)
|
||
|
||
@require_http_methods(["GET"])
|
||
def get_all_logs(request):
|
||
"""Tüm sistem loglarını getir (İşlem Geçmişi için)"""
|
||
try:
|
||
# Tüm backup ve site kontrol loglarını al
|
||
backup_logs = SSHLog.objects.filter(log_type='backup').select_related('ssh_credential')
|
||
command_logs = SSHLog.objects.filter(log_type='command').select_related('ssh_credential')
|
||
|
||
all_logs = []
|
||
|
||
# Backup loglarını ekle
|
||
for log in backup_logs:
|
||
all_logs.append({
|
||
'id': log.id,
|
||
'created_at': log.created_at.isoformat(),
|
||
'log_type': log.log_type,
|
||
'command': log.command,
|
||
'output': log.output,
|
||
'status': log.status,
|
||
'hostname': log.ssh_credential.hostname if log.ssh_credential else 'Bilinmiyor'
|
||
})
|
||
|
||
# Komut loglarını ekle
|
||
for log in command_logs:
|
||
all_logs.append({
|
||
'id': log.id,
|
||
'created_at': log.created_at.isoformat(),
|
||
'log_type': log.log_type,
|
||
'command': log.command,
|
||
'output': log.output,
|
||
'status': log.status,
|
||
'hostname': log.ssh_credential.hostname if log.ssh_credential else 'Bilinmiyor'
|
||
})
|
||
|
||
# Tarihe göre sırala (en yeni önce)
|
||
all_logs.sort(key=lambda x: x['created_at'], reverse=True)
|
||
|
||
return JsonResponse({
|
||
'success': True,
|
||
'logs': all_logs,
|
||
'total_count': len(all_logs)
|
||
})
|
||
|
||
except Exception as e:
|
||
print(f"get_all_logs hatası: {e}")
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': f'Log yükleme hatası: {str(e)}',
|
||
'logs': []
|
||
})
|
||
|
||
def islem_gecmisi(request):
|
||
"""İşlem Geçmişi sayfası"""
|
||
# Tüm logları al
|
||
backup_logs = SSHLog.objects.filter(log_type='backup').select_related('ssh_credential')
|
||
command_logs = SSHLog.objects.filter(log_type='command').select_related('ssh_credential')
|
||
|
||
# Logları birleştir ve tarihe göre sırala
|
||
all_logs = list(backup_logs) + list(command_logs)
|
||
all_logs.sort(key=lambda x: x.created_at, reverse=True)
|
||
|
||
context = {
|
||
'logs': all_logs,
|
||
'page_title': 'İşlem Geçmişi',
|
||
'active_menu': 'islem_gecmisi'
|
||
}
|
||
return render(request, 'ssh_manager/islem_gecmisi.html', context)
|
||
|
||
def host_yonetimi(request):
|
||
"""Host Yönetimi sayfası"""
|
||
ssh_credentials = SSHCredential.objects.all()
|
||
context = {
|
||
'ssh_credentials': ssh_credentials,
|
||
'page_title': 'Host Yönetimi',
|
||
'active_menu': 'host_yonetimi'
|
||
}
|
||
return render(request, 'ssh_manager/host_yonetimi.html', context)
|
||
|
||
def projeler(request):
|
||
"""Projeler sayfası"""
|
||
projects = Project.objects.all()
|
||
context = {
|
||
'projects': projects,
|
||
'page_title': 'Projeler',
|
||
'active_menu': 'projeler'
|
||
}
|
||
return render(request, 'ssh_manager/projeler.html', context)
|
||
|
||
def yedeklemeler(request):
|
||
"""Yedeklemeler sayfası"""
|
||
# Yedekleme kayıtlarını al
|
||
backups = Backup.objects.all().select_related('project', 'project__customer', 'project__ssh_credential').order_by('-start_time')
|
||
|
||
# Filtreler
|
||
status_filter = request.GET.get('status')
|
||
project_filter = request.GET.get('project')
|
||
|
||
if status_filter:
|
||
backups = backups.filter(status=status_filter)
|
||
|
||
if project_filter:
|
||
backups = backups.filter(project_id=project_filter)
|
||
|
||
# İstatistikler
|
||
total_backups = backups.count()
|
||
completed_backups = backups.filter(status='completed').count()
|
||
failed_backups = backups.filter(status='failed').count()
|
||
running_backups = backups.filter(status='running').count()
|
||
|
||
# Son 7 günün yedekleme sayısı
|
||
from datetime import datetime, timedelta
|
||
last_week = datetime.now() - timedelta(days=7)
|
||
recent_backups_count = backups.filter(start_time__gte=last_week).count()
|
||
|
||
# Projeler listesi (filtre için)
|
||
projects = Project.objects.all().order_by('name')
|
||
|
||
context = {
|
||
'backups': backups,
|
||
'projects': projects,
|
||
'backup_stats': {
|
||
'total': total_backups,
|
||
'completed': completed_backups,
|
||
'failed': failed_backups,
|
||
'running': running_backups,
|
||
},
|
||
'total_backups': total_backups,
|
||
'completed_backups': completed_backups,
|
||
'failed_backups': failed_backups,
|
||
'running_backups': running_backups,
|
||
'recent_backups_count': recent_backups_count,
|
||
'status_filter': status_filter,
|
||
'project_filter': project_filter,
|
||
'page_title': 'Yedeklemeler',
|
||
'active_menu': 'yedeklemeler'
|
||
}
|
||
return render(request, 'ssh_manager/yedeklemeler.html', context)
|
||
|
||
def ayarlar(request):
|
||
"""Ayarlar sayfası"""
|
||
from .system_settings import SystemSettings
|
||
|
||
# Ayarları al veya oluştur
|
||
settings, created = SystemSettings.objects.get_or_create(pk=1)
|
||
|
||
if request.method == 'POST':
|
||
# Yedekleme ayarlarını güncelle
|
||
try:
|
||
# Genel yedekleme ayarları
|
||
settings.backup_enabled = request.POST.get('backup_enabled') == 'on'
|
||
settings.backup_frequency = request.POST.get('backup_frequency', 'weekly')
|
||
settings.backup_hour = int(request.POST.get('backup_hour', 3))
|
||
settings.backup_minute = int(request.POST.get('backup_minute', 0))
|
||
|
||
# Seçilen sıklığa göre ek ayarları güncelle
|
||
if settings.backup_frequency == 'weekly':
|
||
settings.backup_day_of_week = int(request.POST.get('backup_day_of_week', 0))
|
||
elif settings.backup_frequency == 'monthly':
|
||
settings.backup_day_of_month = int(request.POST.get('backup_day_of_month', 1))
|
||
|
||
# Yedekleme format ayarı - sadece tar.gz destekleniyor
|
||
settings.backup_format = 'tar.gz'
|
||
|
||
# E-posta bildirim ayarları
|
||
settings.email_notifications = request.POST.get('email_notifications') == 'on'
|
||
settings.notification_email = request.POST.get('notification_email')
|
||
|
||
# Vultr S3 depolama ayarları (her zaman aktif)
|
||
settings.use_s3_storage = True
|
||
settings.s3_access_key = request.POST.get('s3_access_key')
|
||
settings.s3_secret_key = request.POST.get('s3_secret_key')
|
||
settings.s3_bucket_name = request.POST.get('s3_bucket_name')
|
||
settings.s3_region = request.POST.get('s3_region')
|
||
settings.s3_endpoint = request.POST.get('s3_endpoint', 'ams1.vultrobjects.com')
|
||
|
||
settings.save()
|
||
|
||
# Crontab kurulumunu kontrol et
|
||
if settings.backup_enabled:
|
||
setup_crontab(settings)
|
||
|
||
messages.success(request, 'Yedekleme ayarları başarıyla güncellendi!')
|
||
|
||
return redirect('ayarlar')
|
||
|
||
except ValueError as ve:
|
||
messages.error(request, f'Doğrulama hatası: {str(ve)}')
|
||
except Exception as e:
|
||
messages.error(request, f'Hata oluştu: {str(e)}')
|
||
|
||
context = {
|
||
'page_title': 'Ayarlar',
|
||
'active_menu': 'ayarlar',
|
||
'settings': settings
|
||
}
|
||
return render(request, 'ssh_manager/ayarlar.html', context)
|
||
|
||
|
||
def setup_crontab(settings):
|
||
"""Linux crontab yapılandırmasını ayarla - Sadece S3 depolama için"""
|
||
from .ssh_client import SSHManager
|
||
from .models import SSHCredential
|
||
|
||
# Tüm SSH kimlik bilgilerini kontrol et
|
||
credentials = SSHCredential.objects.filter(is_default=True)
|
||
|
||
if not credentials.exists():
|
||
credentials = SSHCredential.objects.all()[:1]
|
||
|
||
if not credentials.exists():
|
||
return False
|
||
|
||
credential = credentials.first()
|
||
ssh_manager = credential.get_manager()
|
||
|
||
|
||
|
||
try:
|
||
if ssh_manager.check_connection():
|
||
# Geçici yedekleme dizini
|
||
temp_backup_dir = "/tmp/backups"
|
||
|
||
# Script detayları
|
||
creation_date = timezone.now().strftime('%Y-%m-%d %H:%M')
|
||
email_notifications = str(settings.email_notifications).lower()
|
||
notification_email = settings.notification_email or "root@localhost"
|
||
bucket_name = settings.s3_bucket_name
|
||
s3_access_key = settings.s3_access_key
|
||
s3_secret_key = settings.s3_secret_key
|
||
s3_region = settings.s3_region
|
||
s3_endpoint = settings.s3_endpoint
|
||
|
||
# Bash script içeriği
|
||
script_content = """#!/bin/bash
|
||
# Otomatik oluşturulan yedekleme betiği (Vultr S3 Özel - Yıl/Ay/Hafta organizasyonlu)
|
||
# Oluşturulma tarihi: {0}
|
||
|
||
# Geçici yedekleme dizini
|
||
TEMP_BACKUP_DIR="{1}"
|
||
mkdir -p $TEMP_BACKUP_DIR
|
||
|
||
# Log dosyası
|
||
LOG_FILE="$TEMP_BACKUP_DIR/backup_$(date +%Y%m%d).log"
|
||
echo "S3 Yedekleme işlemi başlatıldı - $(date)" > $LOG_FILE
|
||
|
||
# AWS CLI kurulum kontrolü
|
||
if ! command -v aws &> /dev/null; then
|
||
echo "AWS CLI bulunamadı, kuruluyor..." >> $LOG_FILE
|
||
pip3 install awscli --upgrade >> $LOG_FILE 2>&1 || apt-get update && apt-get -y install awscli >> $LOG_FILE 2>&1
|
||
fi
|
||
|
||
# S3 kimlik bilgileri
|
||
export AWS_ACCESS_KEY_ID="{2}"
|
||
export AWS_SECRET_ACCESS_KEY="{3}"
|
||
export AWS_DEFAULT_REGION="{4}"
|
||
export AWS_ENDPOINT_URL="https://{5}"
|
||
|
||
# Tüm projeler için yedekleme işlemi
|
||
for PROJECT_DIR in /var/www/*/; do
|
||
if [ -d "$PROJECT_DIR" ]; then
|
||
PROJECT_NAME=$(basename "$PROJECT_DIR")
|
||
echo "Proje $PROJECT_NAME yedekleniyor..." >> $LOG_FILE
|
||
|
||
# Tarih değişkenlerini oluştur
|
||
YEAR=$(date +%Y)
|
||
MONTH=$(date +%m)
|
||
WEEK=$(date +%V)
|
||
DATE_TIME=$(date +%Y%m%d_%H%M%S)
|
||
|
||
# Yedekleme dosyası oluştur
|
||
BACKUP_FILE="$TEMP_BACKUP_DIR/$PROJECT_NAME-$DATE_TIME.tar.gz"
|
||
tar -czf "$BACKUP_FILE" -C /var/www/ "$PROJECT_NAME" --exclude="*/venv/*" --exclude="*/yedek/*" --exclude="*/.idea/*" --exclude="*/.sock/*" --exclude="*/.venv/*" --exclude="*.zip" >> $LOG_FILE 2>&1
|
||
|
||
# Dosya boyutunu kontrol et
|
||
if [ -f "$BACKUP_FILE" ]; then
|
||
FILE_SIZE=$(stat -c%s "$BACKUP_FILE" 2>/dev/null || stat -f%z "$BACKUP_FILE" 2>/dev/null)
|
||
echo "Yedek dosya boyutu: $FILE_SIZE byte" >> $LOG_FILE
|
||
|
||
# Yıllık yedek
|
||
echo "Vultr S3'e yıllık yedek olarak yükleniyor..." >> $LOG_FILE
|
||
aws s3 cp "$BACKUP_FILE" "s3://{6}/$PROJECT_NAME/yearly/$YEAR/$PROJECT_NAME-$DATE_TIME.tar.gz" --endpoint-url="https://{5}" >> $LOG_FILE 2>&1
|
||
|
||
# Aylık yedek
|
||
echo "Vultr S3'e aylık yedek olarak yükleniyor..." >> $LOG_FILE
|
||
aws s3 cp "$BACKUP_FILE" "s3://{6}/$PROJECT_NAME/monthly/$YEAR-$MONTH/$PROJECT_NAME-$DATE_TIME.tar.gz" --endpoint-url="https://{5}" >> $LOG_FILE 2>&1
|
||
|
||
# Haftalık yedek
|
||
echo "Vultr S3'e haftalık yedek olarak yükleniyor..." >> $LOG_FILE
|
||
aws s3 cp "$BACKUP_FILE" "s3://{6}/$PROJECT_NAME/weekly/$YEAR-W$WEEK/$PROJECT_NAME-$DATE_TIME.tar.gz" --endpoint-url="https://{5}" >> $LOG_FILE 2>&1
|
||
|
||
if [ $? -eq 0 ]; then
|
||
echo "Vultr S3'e yükleme başarılı" >> $LOG_FILE
|
||
# Başarılı yükleme sonrası yerel dosyayı sil
|
||
rm -f "$BACKUP_FILE"
|
||
else
|
||
echo "Vultr S3'e yükleme başarısız!" >> $LOG_FILE
|
||
fi
|
||
else
|
||
echo "Yedekleme dosyası oluşturulamadı: $BACKUP_FILE" >> $LOG_FILE
|
||
fi
|
||
fi
|
||
done
|
||
|
||
# Eski geçici dosyaları temizle (3 günden eski)
|
||
find $TEMP_BACKUP_DIR -type f -mtime +3 -delete
|
||
|
||
# E-posta bildirimi gönder
|
||
if [ -f /usr/bin/mail ] && [ "{7}" = "true" ]; then
|
||
echo "Yedekleme özeti gönderiliyor..." >> $LOG_FILE
|
||
cat $LOG_FILE | mail -s "Vultr S3 Yedekleme Özeti - $(date +%Y-%m-%d)" {8}
|
||
fi
|
||
|
||
echo "Yedekleme işlemi tamamlandı - $(date)" >> $LOG_FILE
|
||
""".format(
|
||
creation_date,
|
||
temp_backup_dir,
|
||
s3_access_key,
|
||
s3_secret_key,
|
||
s3_region,
|
||
s3_endpoint,
|
||
bucket_name,
|
||
email_notifications,
|
||
notification_email
|
||
)
|
||
|
||
# Betiği uzak sunucuya yükle
|
||
script_path = "/usr/local/bin/s3_backup.sh"
|
||
ssh_manager.execute_command(f"echo '{script_content}' > {script_path}")
|
||
ssh_manager.execute_command(f"chmod +x {script_path}")
|
||
|
||
# Crontab'a ekle
|
||
cron_expression = settings.backup_crontab_expression
|
||
cron_command = f"{cron_expression} root {script_path} > /dev/null 2>&1"
|
||
|
||
# Mevcut crontab'ı kontrol et ve güncelle
|
||
check_cron = "grep -l 's3_backup.sh' /etc/cron.d/s3_backup 2>/dev/null || echo 'notfound'"
|
||
stdout, stderr, status = ssh_manager.execute_command(check_cron)
|
||
|
||
if not status or 'notfound' in stdout:
|
||
# Crontab dosyasını oluştur
|
||
ssh_manager.execute_command(f"echo '{cron_command}' > /etc/cron.d/s3_backup")
|
||
ssh_manager.execute_command("chmod 644 /etc/cron.d/s3_backup")
|
||
else:
|
||
# Crontab dosyasını güncelle
|
||
ssh_manager.execute_command(f"sed -i 's|.* root /usr/local/bin/s3_backup.sh.*|{cron_command}|' /etc/cron.d/s3_backup")
|
||
|
||
# Eski backup betiklerini temizle
|
||
ssh_manager.execute_command("rm -f /usr/local/bin/auto_backup.sh /etc/cron.d/auto_backup")
|
||
|
||
return True
|
||
except Exception as e:
|
||
print(f"Crontab kurulumu hatası: {str(e)}")
|
||
return False
|
||
finally:
|
||
ssh_manager.close()
|
||
|
||
return False
|
||
|
||
# Müşteri Yönetimi Views
|
||
|
||
def musteriler(request):
|
||
"""Müşteriler sayfası"""
|
||
customers = Customer.objects.all().order_by('-created_at')
|
||
|
||
# Müşteri tipine göre filtrele
|
||
customer_type = request.GET.get('type')
|
||
if customer_type in ['individual', 'corporate']:
|
||
customers = customers.filter(customer_type=customer_type)
|
||
|
||
context = {
|
||
'customers': customers,
|
||
'page_title': 'Müşteriler',
|
||
'active_menu': 'musteriler',
|
||
'filter_type': customer_type
|
||
}
|
||
return render(request, 'ssh_manager/musteriler.html', context)
|
||
|
||
def create_customer(request):
|
||
"""Yeni müşteri oluştur"""
|
||
if request.method == 'POST':
|
||
try:
|
||
customer_type = request.POST.get('customer_type')
|
||
name = request.POST.get('name')
|
||
email = request.POST.get('email')
|
||
|
||
# Zorunlu alan kontrolü
|
||
if not all([customer_type, name, email]):
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': 'Gerekli alanlar eksik!'
|
||
})
|
||
|
||
# E-posta benzersizlik kontrolü
|
||
if Customer.objects.filter(email=email).exists():
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': 'Bu e-posta adresi zaten kullanılıyor!'
|
||
})
|
||
|
||
# Müşteri oluştur
|
||
customer = Customer(
|
||
customer_type=customer_type,
|
||
name=name,
|
||
email=email,
|
||
phone=request.POST.get('phone', ''),
|
||
address=request.POST.get('address', ''),
|
||
notes=request.POST.get('notes', '')
|
||
)
|
||
|
||
# Müşteri tipine göre alanları doldur
|
||
if customer_type == 'individual':
|
||
customer.surname = request.POST.get('surname', '')
|
||
customer.tc_number = request.POST.get('tc_number', '')
|
||
birth_date = request.POST.get('birth_date')
|
||
if birth_date:
|
||
customer.birth_date = birth_date
|
||
elif customer_type == 'corporate':
|
||
customer.company_name = request.POST.get('company_name', '')
|
||
customer.authorized_person = request.POST.get('authorized_person', '')
|
||
customer.tax_number = request.POST.get('tax_number', '')
|
||
customer.tax_office = request.POST.get('tax_office', '')
|
||
|
||
# Validasyon
|
||
customer.full_clean()
|
||
customer.save()
|
||
|
||
return JsonResponse({
|
||
'success': True,
|
||
'message': 'Müşteri başarıyla oluşturuldu!'
|
||
})
|
||
|
||
except ValidationError as e:
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': str(e)
|
||
})
|
||
except Exception as e:
|
||
logger.exception("Müşteri oluşturma hatası")
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': f'Müşteri oluşturulamadı: {str(e)}'
|
||
})
|
||
|
||
return JsonResponse({'success': False, 'message': 'Geçersiz istek!'})
|
||
|
||
def get_customer_details(request, customer_id):
|
||
"""Müşteri detaylarını getir"""
|
||
try:
|
||
customer = get_object_or_404(Customer, id=customer_id)
|
||
|
||
customer_data = {
|
||
'id': customer.id,
|
||
'customer_type': customer.customer_type,
|
||
'name': customer.name,
|
||
'email': customer.email,
|
||
'phone': customer.phone,
|
||
'address': customer.address,
|
||
'notes': customer.notes,
|
||
'surname': customer.surname,
|
||
'tc_number': customer.tc_number,
|
||
'birth_date': customer.birth_date.strftime('%Y-%m-%d') if customer.birth_date else '',
|
||
'company_name': customer.company_name,
|
||
'authorized_person': customer.authorized_person,
|
||
'tax_number': customer.tax_number,
|
||
'tax_office': customer.tax_office,
|
||
}
|
||
|
||
return JsonResponse({
|
||
'success': True,
|
||
'customer': customer_data
|
||
})
|
||
|
||
except Exception as e:
|
||
logger.exception("Müşteri detay alma hatası")
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': f'Müşteri bilgisi alınamadı: {str(e)}'
|
||
})
|
||
|
||
def update_customer(request, customer_id):
|
||
"""Müşteri güncelle"""
|
||
if request.method == 'POST':
|
||
try:
|
||
customer = get_object_or_404(Customer, id=customer_id)
|
||
|
||
customer_type = request.POST.get('customer_type')
|
||
name = request.POST.get('name')
|
||
email = request.POST.get('email')
|
||
|
||
# Zorunlu alan kontrolü
|
||
if not all([customer_type, name, email]):
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': 'Gerekli alanlar eksik!'
|
||
})
|
||
|
||
# E-posta benzersizlik kontrolü (kendisi hariç)
|
||
if Customer.objects.filter(email=email).exclude(id=customer_id).exists():
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': 'Bu e-posta adresi zaten kullanılıyor!'
|
||
})
|
||
|
||
# Müşteriyi güncelle
|
||
customer.customer_type = customer_type
|
||
customer.name = name
|
||
customer.email = email
|
||
customer.phone = request.POST.get('phone', '')
|
||
customer.address = request.POST.get('address', '')
|
||
customer.notes = request.POST.get('notes', '')
|
||
|
||
# Müşteri tipine göre alanları güncelle
|
||
if customer_type == 'individual':
|
||
customer.surname = request.POST.get('surname', '')
|
||
customer.tc_number = request.POST.get('tc_number', '')
|
||
birth_date = request.POST.get('birth_date')
|
||
customer.birth_date = birth_date if birth_date else None
|
||
# Kurumsal alanları temizle
|
||
customer.company_name = ''
|
||
customer.authorized_person = ''
|
||
customer.tax_number = ''
|
||
customer.tax_office = ''
|
||
elif customer_type == 'corporate':
|
||
customer.company_name = request.POST.get('company_name', '')
|
||
customer.authorized_person = request.POST.get('authorized_person', '')
|
||
customer.tax_number = request.POST.get('tax_number', '')
|
||
customer.tax_office = request.POST.get('tax_office', '')
|
||
# Bireysel alanları temizle
|
||
customer.surname = ''
|
||
customer.tc_number = ''
|
||
customer.birth_date = None
|
||
|
||
# Validasyon
|
||
customer.full_clean()
|
||
customer.save()
|
||
|
||
return JsonResponse({
|
||
'success': True,
|
||
'message': 'Müşteri başarıyla güncellendi!'
|
||
})
|
||
|
||
except ValidationError as e:
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': str(e)
|
||
})
|
||
except Exception as e:
|
||
logger.exception("Müşteri güncelleme hatası")
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': f'Müşteri güncellenemedi: {str(e)}'
|
||
})
|
||
|
||
return JsonResponse({'success': False, 'message': 'Geçersiz istek!'})
|
||
|
||
def edit_customer(request, customer_id):
|
||
"""Müşteri düzenleme sayfası (gerekirse)"""
|
||
customer = get_object_or_404(Customer, id=customer_id)
|
||
# Bu view'ı şu an kullanmıyoruz, AJAX ile hallediyoruz
|
||
return redirect('musteriler')
|
||
|
||
def delete_customer(request, customer_id):
|
||
"""Müşteri sil"""
|
||
if request.method == 'POST':
|
||
try:
|
||
customer = get_object_or_404(Customer, id=customer_id)
|
||
|
||
# Müşteriye ait proje kontrolü
|
||
project_count = customer.project_set.count()
|
||
if project_count > 0:
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': f'Bu müşteriye ait {project_count} proje bulunuyor. Önce projeleri silin veya başka müşteriye atayın.'
|
||
})
|
||
|
||
customer_name = str(customer)
|
||
customer.delete()
|
||
|
||
return JsonResponse({
|
||
'success': True,
|
||
'message': f'{customer_name} başarıyla silindi!'
|
||
})
|
||
|
||
except Exception as e:
|
||
logger.exception("Müşteri silme hatası")
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': f'Müşteri silinemedi: {str(e)}'
|
||
})
|
||
|
||
return JsonResponse({'success': False, 'message': 'Geçersiz istek!'})
|
||
|
||
@csrf_exempt
|
||
def test_host_connection(request, host_id):
|
||
"""Host bağlantı testi"""
|
||
if request.method == 'POST':
|
||
try:
|
||
host = SSHCredential.objects.get(id=host_id)
|
||
client = SSHManager(host)
|
||
|
||
# Bağlantı testi ve disk kullanımı güncelleme
|
||
if client.check_connection():
|
||
# Disk kullanımı al
|
||
disk_info = client.get_disk_usage()
|
||
if disk_info and isinstance(disk_info, dict):
|
||
host.disk_usage = disk_info.get('usage_percent')
|
||
|
||
host.connection_status = 'connected'
|
||
host.last_checked = timezone.now()
|
||
host.save()
|
||
|
||
client.close()
|
||
|
||
disk_msg = f" Disk kullanımı: {host.disk_usage}%" if host.disk_usage else ""
|
||
return JsonResponse({
|
||
'success': True,
|
||
'message': f'{host.name} - Bağlantı başarılı!{disk_msg}'
|
||
})
|
||
else:
|
||
host.connection_status = 'failed'
|
||
host.last_checked = timezone.now()
|
||
host.save()
|
||
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': f'{host.name} - Bağlantı başarısız!'
|
||
})
|
||
|
||
except SSHCredential.DoesNotExist:
|
||
return JsonResponse({'success': False, 'message': 'Host bulunamadı'})
|
||
except Exception as e:
|
||
return JsonResponse({'success': False, 'message': f'Hata: {str(e)}'})
|
||
|
||
return JsonResponse({'success': False, 'message': 'Geçersiz istek'})
|
||
|
||
@csrf_exempt
|
||
def refresh_all_hosts(request):
|
||
"""Tüm hostları yenile"""
|
||
if request.method == 'POST':
|
||
try:
|
||
hosts = SSHCredential.objects.all()
|
||
success_count = 0
|
||
total_count = hosts.count()
|
||
|
||
for host in hosts:
|
||
try:
|
||
client = SSHManager(host)
|
||
if client.check_connection():
|
||
# Disk kullanımı al
|
||
disk_info = client.get_disk_usage()
|
||
if disk_info and isinstance(disk_info, dict):
|
||
host.disk_usage = disk_info.get('usage_percent')
|
||
|
||
host.connection_status = 'connected'
|
||
success_count += 1
|
||
else:
|
||
host.connection_status = 'failed'
|
||
|
||
host.last_checked = timezone.now()
|
||
host.save()
|
||
client.close()
|
||
|
||
except Exception as e:
|
||
host.connection_status = 'failed'
|
||
host.last_checked = timezone.now()
|
||
host.save()
|
||
|
||
return JsonResponse({
|
||
'success': True,
|
||
'message': f'{total_count} host kontrol edildi. {success_count} host başarılı.'
|
||
})
|
||
|
||
except Exception as e:
|
||
return JsonResponse({'success': False, 'message': f'Hata: {str(e)}'})
|
||
|
||
return JsonResponse({'success': False, 'message': 'Geçersiz istek'})
|
||
|
||
@csrf_exempt
|
||
def create_host(request):
|
||
"""Yeni host oluştur"""
|
||
if request.method == 'POST':
|
||
try:
|
||
name = request.POST.get('name')
|
||
hostname = request.POST.get('hostname')
|
||
port = request.POST.get('port', 22)
|
||
username = request.POST.get('username')
|
||
password = request.POST.get('password')
|
||
base_path = request.POST.get('base_path', '/var/www')
|
||
is_default = request.POST.get('is_default') == 'on'
|
||
|
||
if not all([name, hostname, username]):
|
||
return JsonResponse({'success': False, 'message': 'Zorunlu alanları doldurun'})
|
||
|
||
# Eğer bu varsayılan olarak ayarlanıyorsa, diğerlerini güncelle
|
||
if is_default:
|
||
SSHCredential.objects.filter(is_default=True).update(is_default=False)
|
||
|
||
host = SSHCredential.objects.create(
|
||
name=name,
|
||
hostname=hostname,
|
||
port=port,
|
||
username=username,
|
||
password=password,
|
||
base_path=base_path,
|
||
is_default=is_default
|
||
)
|
||
|
||
return JsonResponse({
|
||
'success': True,
|
||
'message': f'Host "{name}" başarıyla oluşturuldu'
|
||
})
|
||
|
||
except Exception as e:
|
||
return JsonResponse({'success': False, 'message': f'Hata: {str(e)}'})
|
||
|
||
return JsonResponse({'success': False, 'message': 'Geçersiz istek'})
|
||
|
||
@csrf_exempt
|
||
def update_host(request, host_id):
|
||
"""Host güncelle"""
|
||
if request.method == 'POST':
|
||
try:
|
||
host = SSHCredential.objects.get(id=host_id)
|
||
|
||
host.name = request.POST.get('name', host.name)
|
||
host.hostname = request.POST.get('hostname', host.hostname)
|
||
host.port = request.POST.get('port', host.port)
|
||
host.username = request.POST.get('username', host.username)
|
||
|
||
password = request.POST.get('password')
|
||
if password: # Yalnızca yeni şifre girilmişse güncelle
|
||
host.password = password
|
||
|
||
host.base_path = request.POST.get('base_path', host.base_path)
|
||
|
||
is_default = request.POST.get('is_default') == 'on'
|
||
if is_default and not host.is_default:
|
||
# Diğer varsayılanları kaldır
|
||
SSHCredential.objects.filter(is_default=True).update(is_default=False)
|
||
|
||
host.is_default = is_default
|
||
host.save()
|
||
|
||
return JsonResponse({
|
||
'success': True,
|
||
'message': f'Host "{host.name}" başarıyla güncellendi'
|
||
})
|
||
|
||
except SSHCredential.DoesNotExist:
|
||
return JsonResponse({'success': False, 'message': 'Host bulunamadı'})
|
||
except Exception as e:
|
||
return JsonResponse({'success': False, 'message': f'Hata: {str(e)}'})
|
||
|
||
return JsonResponse({'success': False, 'message': 'Geçersiz istek'})
|
||
|
||
def get_host_details(request, host_id):
|
||
"""Host detaylarını getir"""
|
||
try:
|
||
host = SSHCredential.objects.get(id=host_id)
|
||
return JsonResponse({
|
||
'success': True,
|
||
'host': {
|
||
'id': host.id,
|
||
'name': host.name,
|
||
'hostname': host.hostname,
|
||
'port': host.port,
|
||
'username': host.username,
|
||
'base_path': host.base_path,
|
||
'is_default': host.is_default
|
||
}
|
||
})
|
||
except SSHCredential.DoesNotExist:
|
||
return JsonResponse({'success': False, 'message': 'Host bulunamadı'})
|
||
|
||
@csrf_exempt
|
||
def delete_host(request, host_id):
|
||
"""Host sil"""
|
||
if request.method == 'DELETE':
|
||
try:
|
||
host = SSHCredential.objects.get(id=host_id)
|
||
|
||
# Varsayılan host silinirse uyarı ver
|
||
if host.is_default:
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': 'Varsayılan host silinemez. Önce başka bir host\'u varsayılan yapın.'
|
||
})
|
||
|
||
host_name = host.name
|
||
host.delete()
|
||
|
||
return JsonResponse({
|
||
'success': True,
|
||
'message': f'Host "{host_name}" başarıyla silindi'
|
||
})
|
||
|
||
except SSHCredential.DoesNotExist:
|
||
return JsonResponse({'success': False, 'message': 'Host bulunamadı'})
|
||
except Exception as e:
|
||
return JsonResponse({'success': False, 'message': f'Hata: {str(e)}'})
|
||
|
||
return JsonResponse({'success': False, 'message': 'Geçersiz istek'})
|
||
|
||
@csrf_exempt
|
||
def test_host_connection_form(request):
|
||
"""Form verisiyle bağlantı testi"""
|
||
if request.method == 'POST':
|
||
try:
|
||
hostname = request.POST.get('hostname')
|
||
port = request.POST.get('port', 22)
|
||
username = request.POST.get('username')
|
||
password = request.POST.get('password')
|
||
|
||
if not all([hostname, username]):
|
||
return JsonResponse({'success': False, 'message': 'Hostname ve kullanıcı adı gerekli'})
|
||
|
||
# Geçici SSH credential oluştur
|
||
temp_host = SSHCredential(
|
||
hostname=hostname,
|
||
port=port,
|
||
username=username,
|
||
password=password
|
||
)
|
||
|
||
client = SSHManager(temp_host)
|
||
if client.check_connection():
|
||
client.close()
|
||
return JsonResponse({
|
||
'success': True,
|
||
'message': 'Bağlantı testi başarılı!'
|
||
})
|
||
else:
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': 'Bağlantı testi başarısız!'
|
||
})
|
||
|
||
except Exception as e:
|
||
return JsonResponse({'success': False, 'message': f'Hata: {str(e)}'})
|
||
|
||
return JsonResponse({'success': False, 'message': 'Geçersiz istek'})
|
||
|
||
@csrf_exempt
|
||
def start_backup(request):
|
||
"""Tek proje yedekleme başlat"""
|
||
if request.method == 'POST':
|
||
try:
|
||
project_id = request.POST.get('project_id')
|
||
backup_type = request.POST.get('backup_type', 'full')
|
||
compress = request.POST.get('compress') == 'on'
|
||
note = request.POST.get('note', '')
|
||
|
||
if not project_id:
|
||
return JsonResponse({'success': False, 'message': 'Proje ID gerekli'})
|
||
|
||
project = Project.objects.get(id=project_id)
|
||
|
||
# Yedekleme işlemini başlat (arka planda)
|
||
from threading import Thread
|
||
|
||
def backup_project():
|
||
try:
|
||
ssh_manager = SSHManager(project.ssh_credential)
|
||
|
||
# Log kaydı oluştur
|
||
log = SSHLog.objects.create(
|
||
ssh_credential=project.ssh_credential,
|
||
log_type='backup',
|
||
command=f'Backup {project.name} ({backup_type})',
|
||
status='running'
|
||
)
|
||
|
||
if ssh_manager.check_connection():
|
||
# Yedekleme komutlarını çalıştır
|
||
backup_commands = []
|
||
|
||
if backup_type in ['full', 'files']:
|
||
# Dosya yedekleme
|
||
if compress:
|
||
backup_commands.append(f'cd {project.ssh_credential.base_path} && tar -czf {project.folder_name}_backup_{log.created_at.strftime("%Y%m%d_%H%M%S")}.tar.gz {project.folder_name}/')
|
||
else:
|
||
backup_commands.append(f'cd {project.ssh_credential.base_path} && cp -r {project.folder_name} {project.folder_name}_backup_{log.created_at.strftime("%Y%m%d_%H%M%S")}')
|
||
|
||
if backup_type in ['full', 'database']:
|
||
# Veritabanı yedekleme (örnek MySQL)
|
||
backup_commands.append(f'mysqldump -u username -p password database_name > {project.folder_name}_db_backup_{log.created_at.strftime("%Y%m%d_%H%M%S")}.sql')
|
||
|
||
outputs = []
|
||
for cmd in backup_commands:
|
||
output = ssh_manager.execute_command(cmd)
|
||
outputs.append(f"Command: {cmd}\nOutput: {output}")
|
||
|
||
log.output = '\n\n'.join(outputs)
|
||
log.status = 'success'
|
||
|
||
# Proje son yedekleme tarihini güncelle
|
||
project.last_backup = timezone.now()
|
||
project.save()
|
||
else:
|
||
log.output = 'SSH bağlantı hatası'
|
||
log.status = 'error'
|
||
|
||
log.save()
|
||
ssh_manager.close()
|
||
|
||
except Exception as e:
|
||
log.output = f'Yedekleme hatası: {str(e)}'
|
||
log.status = 'error'
|
||
log.save()
|
||
|
||
# Arka planda çalıştır
|
||
backup_thread = Thread(target=backup_project)
|
||
backup_thread.start();
|
||
|
||
return JsonResponse({
|
||
'success': True,
|
||
'message': f'{project.name} projesi için yedekleme başlatıldı'
|
||
})
|
||
|
||
except Project.DoesNotExist:
|
||
return JsonResponse({'success': False, 'message': 'Proje bulunamadı'})
|
||
except Exception as e:
|
||
return JsonResponse({'success': False, 'message': f'Hata: {str(e)}'})
|
||
|
||
return JsonResponse({'success': False, 'message': 'Geçersiz istek'})
|
||
|
||
@csrf_exempt
|
||
def backup_all_projects(request):
|
||
"""Tüm projeleri yedekle"""
|
||
if request.method == 'POST':
|
||
try:
|
||
projects = Project.objects.filter(ssh_credential__isnull=False)
|
||
|
||
if not projects.exists():
|
||
return JsonResponse({'success': False, 'message': 'Yedeklenecek proje bulunamadı'})
|
||
|
||
# Her proje için yedekleme başlat
|
||
from threading import Thread
|
||
|
||
def backup_all():
|
||
for project in projects:
|
||
try:
|
||
ssh_manager = SSHManager(project.ssh_credential)
|
||
|
||
log = SSHLog.objects.create(
|
||
ssh_credential=project.ssh_credential,
|
||
log_type='backup',
|
||
command=f'Auto backup {project.name}',
|
||
status='running'
|
||
)
|
||
|
||
if ssh_manager.check_connection():
|
||
# Basit dosya yedekleme
|
||
cmd = f'cd {project.ssh_credential.base_path} && tar -czf {project.folder_name}_auto_backup_{log.created_at.strftime("%Y%m%d_%H%M%S")}.tar.gz {project.folder_name}/'
|
||
output = ssh_manager.execute_command(cmd)
|
||
|
||
log.output = f"Command: {cmd}\nOutput: {output}"
|
||
log.status = 'success'
|
||
|
||
project.last_backup = timezone.now()
|
||
project.save()
|
||
else:
|
||
log.output = 'SSH bağlantı hatası'
|
||
log.status = 'error'
|
||
|
||
log.save()
|
||
ssh_manager.close()
|
||
|
||
except Exception as e:
|
||
log.output = f'Yedekleme hatası: {str(e)}'
|
||
log.status = 'error'
|
||
log.save()
|
||
|
||
backup_thread = Thread(target=backup_all)
|
||
backup_thread.start()
|
||
|
||
return JsonResponse({
|
||
'success': True,
|
||
'message': f'{projects.count()} proje için toplu yedekleme başlatıldı'
|
||
})
|
||
|
||
except Exception as e:
|
||
return JsonResponse({'success': False, 'message': f'Hata: {str(e)}'})
|
||
|
||
return JsonResponse({'success': False, 'message': 'Geçersiz istek'})
|
||
|
||
@csrf_exempt
|
||
def retry_backup(request):
|
||
"""Yedeklemeyi tekrar dene"""
|
||
if request.method == 'POST':
|
||
try:
|
||
import json
|
||
data = json.loads(request.body)
|
||
project_id = data.get('project_id')
|
||
|
||
if not project_id:
|
||
return JsonResponse({'success': False, 'message': 'Proje ID gerekli'})
|
||
|
||
project = Project.objects.get(id=project_id)
|
||
|
||
# start_backup fonksiyonunu çağır
|
||
from django.test import RequestFactory
|
||
factory = RequestFactory()
|
||
retry_request = factory.post('/start-backup/', {
|
||
'project_id': project_id,
|
||
'backup_type': 'full',
|
||
'compress': 'on'
|
||
})
|
||
retry_request.META['HTTP_X_CSRFTOKEN'] = request.META.get('HTTP_X_CSRFTOKEN')
|
||
|
||
return start_backup(retry_request)
|
||
|
||
except Project.DoesNotExist:
|
||
return JsonResponse({'success': False, 'message': 'Proje bulunamadı'})
|
||
except Exception as e:
|
||
return JsonResponse({'success': False, 'message': f'Hata: {str(e)}'})
|
||
|
||
return JsonResponse({'success': False, 'message': 'Geçersiz istek'})
|
||
|
||
@require_http_methods(["GET"])
|
||
def backup_details(request, backup_id):
|
||
"""Backup detaylarını getir"""
|
||
try:
|
||
backup = get_object_or_404(Backup, id=backup_id)
|
||
data = {
|
||
'success': True,
|
||
'backup': {
|
||
'id': backup.id,
|
||
'project_name': backup.project.name,
|
||
'project_folder': backup.project.folder_name,
|
||
'host_name': backup.project.ssh_credential.hostname,
|
||
'backup_type': backup.get_backup_type_display(),
|
||
'status': backup.get_status_display(),
|
||
'start_time': backup.start_time.strftime('%d.%m.%Y %H:%M:%S'),
|
||
'end_time': backup.end_time.strftime('%d.%m.%Y %H:%M:%S') if backup.end_time else None,
|
||
'duration': backup.duration,
|
||
'file_path': backup.file_path,
|
||
'file_size': backup.file_size,
|
||
'error_message': backup.error_message,
|
||
'notes': backup.notes,
|
||
}
|
||
}
|
||
return JsonResponse(data)
|
||
except Exception as e:
|
||
return JsonResponse({'success': False, 'message': 'Backup detayları alınırken hata oluştu.'})
|
||
|
||
@require_http_methods(["POST"])
|
||
def cancel_backup(request, backup_id):
|
||
"""Devam eden backup'ı iptal et"""
|
||
try:
|
||
backup = get_object_or_404(Backup, id=backup_id)
|
||
|
||
if backup.status != 'running':
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': 'Sadece devam eden yedeklemeler iptal edilebilir'
|
||
})
|
||
|
||
backup.status = 'cancelled'
|
||
backup.end_time = timezone.now()
|
||
backup.error_message = 'Kullanıcı tarafından iptal edildi'
|
||
backup.save()
|
||
|
||
return JsonResponse({
|
||
'success': True,
|
||
'message': 'Yedekleme başarıyla iptal edildi'
|
||
})
|
||
|
||
except Exception as e:
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': 'Yedekleme iptal edilirken hata oluştu'
|
||
})
|
||
|
||
@require_http_methods(["POST"])
|
||
def delete_backup_record(request, backup_id):
|
||
"""Backup kaydını sil"""
|
||
try:
|
||
backup = get_object_or_404(Backup, id=backup_id)
|
||
|
||
# Devam eden backup silinemez
|
||
if backup.status == 'running':
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': 'Devam eden yedekleme kaydı silinemez. Önce iptal edin.'
|
||
})
|
||
|
||
backup.delete()
|
||
|
||
return JsonResponse({
|
||
'success': True,
|
||
'message': 'Yedekleme kaydı başarıyla silindi'
|
||
})
|
||
|
||
except Exception as e:
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': 'Kayıt silinirken hata oluştu'
|
||
})
|
||
|
||
@login_required
|
||
@require_http_methods(["POST"])
|
||
def renew_host(request, project_id):
|
||
"""Projenin host yenileme tarihini domain bitiş tarihine veya 1 yıl ileriye al"""
|
||
try:
|
||
project = get_object_or_404(Project, id=project_id)
|
||
from datetime import date, datetime, timedelta
|
||
import calendar
|
||
import json # JSON import'u ekle
|
||
|
||
# Request body'den expiration_date var mı kontrol et
|
||
if request.method == 'POST' and request.body:
|
||
try:
|
||
data = json.loads(request.body)
|
||
expiration_date_str = data.get('expiration_date')
|
||
|
||
if expiration_date_str:
|
||
# ISO formatında tarih geldiğini varsayalım (YYYY-MM-DD)
|
||
try:
|
||
next_year = datetime.fromisoformat(expiration_date_str).date()
|
||
renewal_source = f"Domain expiration tarihi: {expiration_date_str}"
|
||
except ValueError:
|
||
# Tarih parse edilemezse 1 yıl sonrasını hesapla
|
||
logger.warning(f"Geçersiz tarih formatı: {expiration_date_str}")
|
||
today = date.today()
|
||
try:
|
||
next_year = today.replace(year=today.year + 1)
|
||
except ValueError:
|
||
next_year = today.replace(year=today.year + 1, day=28)
|
||
renewal_source = "Manuel yenileme (geçersiz tarih formatı nedeniyle)"
|
||
else:
|
||
# Tarih yoksa 1 yıl sonrasını hesapla
|
||
renewal_source = "Manuel yenileme (1 yıl)"
|
||
today = date.today()
|
||
try:
|
||
next_year = today.replace(year=today.year + 1)
|
||
except ValueError:
|
||
# 29 Şubat durumu için (artık yıldan normal yıla geçiş)
|
||
next_year = today.replace(year=today.year + 1, day=28)
|
||
except json.JSONDecodeError as json_error:
|
||
# JSON parse edilemezse 1 yıl sonrasını hesapla
|
||
logger.warning(f"JSON parse hatası: {json_error}")
|
||
renewal_source = "Manuel yenileme (JSON parse hatası)"
|
||
today = date.today()
|
||
try:
|
||
next_year = today.replace(year=today.year + 1)
|
||
except ValueError:
|
||
# 29 Şubat durumu için (artık yıldan normal yıla geçiş)
|
||
next_year = today.replace(year=today.year + 1, day=28)
|
||
else:
|
||
# POST değilse veya body yoksa 1 yıl sonrasını hesapla
|
||
renewal_source = "Manuel yenileme (1 yıl)"
|
||
today = date.today()
|
||
try:
|
||
next_year = today.replace(year=today.year + 1)
|
||
except ValueError:
|
||
# 29 Şubat durumu için (artık yıldan normal yıla geçiş)
|
||
next_year = today.replace(year=today.year + 1, day=28)
|
||
|
||
# Eski tarihi logla
|
||
old_date = project.host_renewal_date
|
||
print(f"=== HOST RENEWAL UPDATE DEBUG ===")
|
||
print(f"Project ID: {project_id}")
|
||
print(f"Project Name: {project.name}")
|
||
print(f"Old renewal date: {old_date}")
|
||
print(f"New renewal date: {next_year}")
|
||
print(f"Renewal source: {renewal_source}")
|
||
|
||
# Yeni tarihi ayarla
|
||
project.host_renewal_date = next_year
|
||
project.save()
|
||
|
||
# Kaydedildi mi kontrol et
|
||
project.refresh_from_db()
|
||
print(f"Database'den tekrar okunan tarih: {project.host_renewal_date}")
|
||
|
||
# Log kaydı oluştur
|
||
log_message = f"Host yenileme tarihi güncellendi. Eski tarih: {old_date or 'Yok'}, Yeni tarih: {next_year}, Kaynak: {renewal_source}"
|
||
|
||
SSHLog.objects.create(
|
||
ssh_credential=project.ssh_credential,
|
||
log_type='command',
|
||
command="Host Yenileme",
|
||
output=log_message,
|
||
status=True
|
||
)
|
||
|
||
logger.info(f"Proje {project.name} (ID: {project_id}) host yenileme tarihi güncellendi: {next_year}")
|
||
|
||
return JsonResponse({
|
||
'success': True,
|
||
'message': f'Host yenileme tarihi {next_year.strftime("%d.%m.%Y")} olarak güncellendi',
|
||
'old_date': old_date.strftime("%d.%m.%Y") if old_date else None,
|
||
'new_date': next_year.strftime("%d.%m.%Y"),
|
||
'project_id': project_id,
|
||
'project_name': project.name,
|
||
'renewal_source': renewal_source,
|
||
'debug': {
|
||
'old_date_raw': str(old_date),
|
||
'new_date_raw': str(next_year),
|
||
'saved_successfully': True
|
||
}
|
||
})
|
||
|
||
except Exception as e:
|
||
logger.exception(f"Host yenileme hatası (Proje ID: {project_id}): {str(e)}")
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': f'Host yenileme sırasında hata oluştu: {str(e)}',
|
||
'debug': f'Error type: {type(e).__name__}'
|
||
}, status=500)
|
||
|
||
@login_required
|
||
def update_hosts_status(request):
|
||
"""Tüm hostların bağlantı durumunu ve disk kullanım bilgisini güncelle - HTTP view"""
|
||
if request.method == 'POST':
|
||
try:
|
||
# Mevcut utility fonksiyonu çağır
|
||
update_all_hosts_status()
|
||
|
||
messages.success(request, "Tüm hostların durumu başarıyla güncellendi.")
|
||
return JsonResponse({
|
||
'success': True,
|
||
'message': 'Tüm hostların durumu başarıyla güncellendi.'
|
||
})
|
||
except Exception as e:
|
||
logger.exception("Host durumu güncelleme hatası")
|
||
messages.error(request, f"Host durumu güncellenirken bir hata oluştu: {str(e)}")
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': f'Host durumu güncellenirken bir hata oluştu: {str(e)}'
|
||
}, status=500)
|
||
else:
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': 'Bu işlem için POST metodu gerekli'
|
||
}, status=400)
|
||
|
||
@require_http_methods(["GET"])
|
||
def get_project_meta_key(request, project_id):
|
||
"""Proje için meta verification key döndür"""
|
||
try:
|
||
project = get_object_or_404(Project, id=project_id)
|
||
|
||
# Meta key yoksa oluştur
|
||
if not project.meta_key:
|
||
project.generate_meta_key()
|
||
project.save()
|
||
|
||
# Meta tag'ı al
|
||
primary_meta, all_metas, comment_tag = project.get_meta_tag()
|
||
|
||
return JsonResponse({
|
||
'success': True,
|
||
'meta_key': primary_meta,
|
||
'all_formats': all_metas,
|
||
'comment_format': comment_tag,
|
||
'project_name': project.name,
|
||
'project_url': project.url
|
||
})
|
||
|
||
except Exception as e:
|
||
logger.exception(f"Meta key alma hatası (Proje ID: {project_id}): {str(e)}")
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': f'Meta key alınırken hata oluştu: {str(e)}'
|
||
}, status=500)
|