2495 lines
92 KiB
Python
2495 lines
92 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 .backup import job
|
||
from .models import SSHCredential, Project, SSHLog, Customer
|
||
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__)
|
||
|
||
@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):
|
||
try:
|
||
project = get_object_or_404(Project, id=project_id)
|
||
folder_name = project.folder_name
|
||
calisma_dizini = f"{project.ssh_credential.base_path}/{folder_name}"
|
||
|
||
if not folder_name:
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': 'Klasör adı bulunamadı'
|
||
})
|
||
|
||
try:
|
||
# Önce klasörün varlığını kontrol et
|
||
ssh_manager = project.ssh_credential.get_manager()
|
||
check_cmd = f'test -d "{calisma_dizini}" && echo "exists"'
|
||
stdout, stderr, status = ssh_manager.execute_command(check_cmd)
|
||
|
||
if not status or stdout.strip() != "exists":
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': 'Yedeklenecek klasör bulunamadı'
|
||
})
|
||
|
||
# Backup işlemini başlat
|
||
result = job(folder_name, calisma_dizini, project_id)
|
||
|
||
if not result.get('success'):
|
||
raise Exception(result.get('message', 'Backup işlemi başarısız oldu'))
|
||
|
||
# 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:
|
||
error_msg = str(e)
|
||
if 'NoSuchBucket' in error_msg:
|
||
error_msg = 'Backup bucket\'ı bulunamadı. Sistem yöneticinize başvurun.'
|
||
|
||
# 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 '',
|
||
'last_backup': project.last_backup.strftime('%d.%m.%Y %H:%M') if project.last_backup else None,
|
||
'disk_usage': project.disk_usage or '0B',
|
||
}
|
||
}
|
||
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', '')
|
||
|
||
# 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
|
||
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:
|
||
status, message = check_site_status(project)
|
||
|
||
# Host bilgilerini güncelle (bağlantı durumu ve disk kullanımı)
|
||
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
|
||
|
||
# Disk kullanım bilgisini al (sadece online ise)
|
||
if is_online:
|
||
disk_usage_info = ssh_manager.get_disk_usage()
|
||
if disk_usage_info:
|
||
# Dictionary'yi string'e çevir (görüntüleme için)
|
||
project.ssh_credential.disk_usage = f"{disk_usage_info['used']} / {disk_usage_info['total']} ({disk_usage_info['usage_percent']}%)"
|
||
else:
|
||
project.ssh_credential.disk_usage = None
|
||
else:
|
||
project.ssh_credential.disk_usage = None
|
||
|
||
project.ssh_credential.save()
|
||
|
||
except Exception as e:
|
||
# Hata durumunda offline olarak işaretle
|
||
project.ssh_credential.is_online = False
|
||
project.ssh_credential.disk_usage = None
|
||
project.ssh_credential.save()
|
||
print(f"Host bilgi güncelleme hatası: {e}")
|
||
finally:
|
||
ssh_manager.close()
|
||
|
||
# Log kaydını güncelle
|
||
log_entry.output = message
|
||
log_entry.status = status
|
||
log_entry.save()
|
||
|
||
return JsonResponse({
|
||
'success': True,
|
||
'status': status,
|
||
'message': message,
|
||
'is_active': project.is_site_active,
|
||
'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"Site kontrol hatası: {str(e)}"
|
||
log_entry.status = False
|
||
log_entry.save()
|
||
raise e
|
||
|
||
except Exception as e:
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': f'Site kontrol hatası: {str(e)}'
|
||
}, status=500)
|
||
|
||
|
||
@require_http_methods(["GET"])
|
||
def get_project_meta_key(request, project_id):
|
||
"""Projenin meta key'ini döndür"""
|
||
try:
|
||
project = get_object_or_404(Project, id=project_id)
|
||
|
||
if not project.meta_key:
|
||
project.generate_meta_key()
|
||
project.save()
|
||
|
||
return JsonResponse({
|
||
'success': True,
|
||
'meta_key': project.meta_key,
|
||
'meta_tag': project.get_meta_tag(),
|
||
'instructions': 'Bu meta tag\'ı sitenizin <head> bölümüne ekleyin'
|
||
})
|
||
|
||
except Exception as e:
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': f'Meta key hatası: {str(e)}'
|
||
}, status=500)
|
||
|
||
|
||
@require_http_methods(["POST"])
|
||
def check_all_sites_view(request):
|
||
"""Tüm projelerin site durumunu kontrol et"""
|
||
try:
|
||
from .utils import check_all_sites
|
||
results = check_all_sites()
|
||
|
||
return JsonResponse({
|
||
'success': True,
|
||
'results': [
|
||
{
|
||
'project_id': result['project'].id,
|
||
'project_name': result['project'].name,
|
||
'status': result['status'],
|
||
'message': result['message']
|
||
}
|
||
for result in results
|
||
]
|
||
})
|
||
|
||
except Exception as e:
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': f'Toplu kontrol hatası: {str(e)}'
|
||
}, status=500)
|
||
|
||
@csrf_exempt
|
||
def update_hosts_status(request):
|
||
"""Tüm hostların durumunu güncelle"""
|
||
print(f"update_hosts_status çağrıldı, method: {request.method}")
|
||
|
||
if request.method == 'POST':
|
||
try:
|
||
print("update_all_hosts_status fonksiyonu çağrılıyor...")
|
||
update_all_hosts_status()
|
||
print("update_all_hosts_status başarıyla tamamlandı")
|
||
return JsonResponse({
|
||
'success': True,
|
||
'message': 'Tüm host bilgileri güncellendi'
|
||
})
|
||
except Exception as e:
|
||
print(f"update_hosts_status hatası: {e}")
|
||
return JsonResponse({
|
||
'success': False,
|
||
'message': f'Host güncelleme hatası: {str(e)}'
|
||
})
|
||
|
||
print("Geçersiz istek (POST değil)")
|
||
return JsonResponse({'success': False, 'message': 'Geçersiz istek'})
|
||
|
||
@csrf_exempt
|
||
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 loglarını al
|
||
backup_logs = SSHLog.objects.filter(log_type='backup').select_related('ssh_credential').order_by('-created_at')
|
||
|
||
# İstatistikler
|
||
total_backups = backup_logs.count()
|
||
successful_backups = backup_logs.filter(status='success').count()
|
||
failed_backups = backup_logs.filter(status='error').count()
|
||
|
||
context = {
|
||
'backup_logs': backup_logs,
|
||
'total_backups': total_backups,
|
||
'successful_backups': successful_backups,
|
||
'failed_backups': failed_backups,
|
||
'page_title': 'Yedeklemeler',
|
||
'active_menu': 'yedeklemeler'
|
||
}
|
||
return render(request, 'ssh_manager/yedeklemeler.html', context)
|
||
|
||
def ayarlar(request):
|
||
"""Ayarlar sayfası"""
|
||
context = {
|
||
'page_title': 'Ayarlar',
|
||
'active_menu': 'ayarlar'
|
||
}
|
||
return render(request, 'ssh_manager/ayarlar.html', context)
|
||
|
||
# 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 siliniyorsa 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'})
|