yeni
This commit is contained in:
607
ssh_manager/ssh_client.py
Normal file
607
ssh_manager/ssh_client.py
Normal file
@ -0,0 +1,607 @@
|
||||
import paramiko
|
||||
import logging
|
||||
import os
|
||||
import tempfile
|
||||
from django.utils import timezone
|
||||
from django.template.loader import render_to_string
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class SSHManager:
|
||||
def __init__(self, ssh_credential):
|
||||
self.ssh_credential = ssh_credential
|
||||
self.client = None
|
||||
self.connect()
|
||||
logger.info(f'SSHManager başlatıldı: {ssh_credential.hostname}')
|
||||
|
||||
def connect(self):
|
||||
"""SSH bağlantısı kur"""
|
||||
try:
|
||||
self.client = paramiko.SSHClient()
|
||||
self.client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
self.client.connect(
|
||||
hostname=self.ssh_credential.hostname,
|
||||
username=self.ssh_credential.username,
|
||||
password=self.ssh_credential.password,
|
||||
port=self.ssh_credential.port or 22,
|
||||
look_for_keys=False,
|
||||
allow_agent=False
|
||||
)
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.error(f'SSH bağlantı hatası: {str(e)}')
|
||||
return False
|
||||
|
||||
def close(self):
|
||||
"""SSH bağlantısını kapat"""
|
||||
if self.client:
|
||||
self.client.close()
|
||||
self.client = None
|
||||
|
||||
def check_connection(self):
|
||||
"""SSH bağlantısını kontrol et"""
|
||||
try:
|
||||
if not self.client:
|
||||
return self.connect()
|
||||
self.client.exec_command('echo "Connection test"')
|
||||
return True
|
||||
except:
|
||||
return self.connect()
|
||||
|
||||
def execute_command(self, command):
|
||||
"""
|
||||
SSH üzerinden komut çalıştır ve sonuçları döndür
|
||||
"""
|
||||
try:
|
||||
if not self.client:
|
||||
self.connect()
|
||||
|
||||
stdin, stdout, stderr = self.client.exec_command(command)
|
||||
exit_status = stdout.channel.recv_exit_status()
|
||||
|
||||
# Binary veriyi oku
|
||||
stdout_data = stdout.read()
|
||||
stderr_data = stderr.read()
|
||||
|
||||
# Farklı encoding'leri dene
|
||||
encodings = ['utf-8', 'latin1', 'cp1252', 'iso-8859-9']
|
||||
|
||||
# stdout için encoding dene
|
||||
stdout_str = None
|
||||
for enc in encodings:
|
||||
try:
|
||||
stdout_str = stdout_data.decode(enc)
|
||||
break
|
||||
except UnicodeDecodeError:
|
||||
continue
|
||||
|
||||
# stderr için encoding dene
|
||||
stderr_str = None
|
||||
for enc in encodings:
|
||||
try:
|
||||
stderr_str = stderr_data.decode(enc)
|
||||
break
|
||||
except UnicodeDecodeError:
|
||||
continue
|
||||
|
||||
# Eğer hiçbir encoding çalışmazsa, latin1 kullan (her byte'ı decode edebilir)
|
||||
if stdout_str is None:
|
||||
stdout_str = stdout_data.decode('latin1')
|
||||
if stderr_str is None:
|
||||
stderr_str = stderr_data.decode('latin1')
|
||||
|
||||
return stdout_str, stderr_str, exit_status == 0
|
||||
|
||||
except Exception as e:
|
||||
logger.exception(f"Komut çalıştırma hatası: {command}")
|
||||
return "", str(e), False
|
||||
|
||||
def download_req_file(self, project):
|
||||
"""req.txt dosyasını oku ve geçici dosya olarak kaydet"""
|
||||
try:
|
||||
# Dosya içeriğini oku
|
||||
cmd = f'cat "{project.get_full_path()}/req.txt"'
|
||||
stdout, stderr, status = self.execute_command(cmd)
|
||||
|
||||
if not status:
|
||||
logger.error(f"req.txt okunamadı: {stderr}")
|
||||
return None
|
||||
|
||||
# Geçici dosya oluştur
|
||||
temp = tempfile.NamedTemporaryFile(mode='w+', delete=False, suffix='.txt')
|
||||
temp.write(stdout)
|
||||
temp.close()
|
||||
|
||||
logger.info(f"req.txt temp file created: {temp.name}")
|
||||
return temp.name
|
||||
|
||||
except Exception as e:
|
||||
logger.exception(f"Error in download_req_file: {str(e)}")
|
||||
return None
|
||||
|
||||
def delete_project(self, project):
|
||||
"""Proje klasörünü sil"""
|
||||
try:
|
||||
cmd = f'rm -rf "{project.get_full_path()}"'
|
||||
stdout, stderr, status = self.execute_command(cmd)
|
||||
|
||||
if status:
|
||||
return True, "Proje başarıyla silindi"
|
||||
else:
|
||||
return False, f"Silme hatası: {stderr}"
|
||||
|
||||
except Exception as e:
|
||||
return False, str(e)
|
||||
|
||||
def upload_zip(self, project, zip_file):
|
||||
"""ZIP dosyasını yükle ve aç"""
|
||||
try:
|
||||
# Geçici dizin oluştur
|
||||
temp_dir = '/tmp/project_upload'
|
||||
mkdir_out, mkdir_err, mkdir_status = self.execute_command(f'rm -rf {temp_dir} && mkdir -p {temp_dir}')
|
||||
if not mkdir_status:
|
||||
return False, f'Geçici dizin oluşturulamadı: {mkdir_err}'
|
||||
|
||||
# SFTP bağlantısı
|
||||
sftp = self.client.open_sftp()
|
||||
|
||||
try:
|
||||
# ZIP dosyasını yükle
|
||||
remote_zip = f"{temp_dir}/{zip_file.name}"
|
||||
sftp.putfo(zip_file, remote_zip)
|
||||
|
||||
# ZIP dosyasını aç
|
||||
unzip_cmd = f'''
|
||||
cd {temp_dir} && \
|
||||
unzip -o "{zip_file.name}" && \
|
||||
rm "{zip_file.name}" && \
|
||||
mv * "{project.get_full_path()}/" 2>/dev/null || true && \
|
||||
cd / && \
|
||||
rm -rf {temp_dir}
|
||||
'''
|
||||
|
||||
stdout, stderr, status = self.execute_command(unzip_cmd)
|
||||
|
||||
if not status:
|
||||
return False, f'ZIP açma hatası: {stderr}'
|
||||
|
||||
return True, "Dosya başarıyla yüklendi"
|
||||
|
||||
finally:
|
||||
sftp.close()
|
||||
|
||||
except Exception as e:
|
||||
return False, str(e)
|
||||
|
||||
def upload_txt(self, project, txt_file):
|
||||
"""TXT dosyasını yükle"""
|
||||
try:
|
||||
# SFTP bağlantısı
|
||||
sftp = self.client.open_sftp()
|
||||
|
||||
try:
|
||||
# Dosya adını belirle
|
||||
remote_path = f"{project.get_full_path()}/req.txt"
|
||||
|
||||
# Dosyayı yükle
|
||||
sftp.putfo(txt_file, remote_path)
|
||||
|
||||
# İzinleri ayarla
|
||||
self.execute_command(f'chmod 644 "{remote_path}"')
|
||||
|
||||
return True, "Dosya başarıyla yüklendi"
|
||||
|
||||
finally:
|
||||
sftp.close()
|
||||
|
||||
except Exception as e:
|
||||
return False, str(e)
|
||||
|
||||
def create_config_files(self, project):
|
||||
"""Tüm konfigürasyon dosyalarını oluşturur"""
|
||||
try:
|
||||
logger.info(f'"{project.folder_name}" projesi için konfigürasyon dosyaları oluşturuluyor')
|
||||
|
||||
# Değişkenleri hazırla
|
||||
context = {
|
||||
'project_name': project.folder_name,
|
||||
'project_path': project.get_full_path(),
|
||||
'domain_name': project.url
|
||||
}
|
||||
logger.info('Konfigürasyon şablonları için context hazırlandı')
|
||||
|
||||
# Konfigürasyon içeriklerini hazırla
|
||||
configs = {
|
||||
'nginx.conf': render_to_string('ssh_manager/nginx.conf.template', context),
|
||||
'supervisor.conf': render_to_string('ssh_manager/supervisor.conf.template', context),
|
||||
'wsgi_conf': render_to_string('ssh_manager/wsgi.conf.template', context)
|
||||
}
|
||||
logger.info('Konfigürasyon şablonları render edildi')
|
||||
|
||||
# WSGI dosyasını proje dizininde oluştur
|
||||
logger.info('WSGI dosyası oluşturuluyor')
|
||||
wsgi_cmd = f'cat > "{project.get_full_path()}/wsgi_conf" << "EOF"\n{configs["wsgi_conf"]}\nEOF'
|
||||
stdout, stderr, status = self.execute_command(wsgi_cmd)
|
||||
|
||||
if not status:
|
||||
logger.error(f'WSGI dosyası oluşturma hatası: {stderr}')
|
||||
raise Exception(f'WSGI dosyası oluşturulamadı: {stderr}')
|
||||
logger.info('WSGI dosyası başarıyla oluşturuldu')
|
||||
|
||||
# WSGI için izinleri ayarla
|
||||
logger.info('WSGI dosyası için çalıştırma izinleri ayarlanıyor')
|
||||
chmod_cmd = f'chmod +x "{project.get_full_path()}/wsgi_conf"'
|
||||
stdout, stderr, status = self.execute_command(chmod_cmd)
|
||||
if not status:
|
||||
logger.error(f'WSGI izin ayarlama hatası: {stderr}')
|
||||
raise Exception(f'WSGI için izinler ayarlanamadı: {stderr}')
|
||||
logger.info('WSGI dosyası için izinler başarıyla ayarlandı')
|
||||
|
||||
# Nginx konfigürasyonunu direkt hedef konumunda oluştur
|
||||
if project.url:
|
||||
logger.info('Nginx konfigürasyonu ayarlanıyor')
|
||||
nginx_target = f'/etc/nginx/sites-available/{project.url}'
|
||||
nginx_enabled = f'/etc/nginx/sites-enabled/{project.url}'
|
||||
|
||||
# Eski konfigürasyonları temizle
|
||||
logger.info('Eski Nginx konfigürasyonları temizleniyor')
|
||||
self.execute_command(f'sudo rm -f {nginx_target} {nginx_enabled}')
|
||||
|
||||
# Yeni konfigürasyonu oluştur
|
||||
logger.info(f'Nginx konfigürasyonu "{nginx_target}" konumunda oluşturuluyor')
|
||||
nginx_cmd = f'sudo bash -c \'cat > "{nginx_target}" << "EOF"\n{configs["nginx.conf"]}\nEOF\''
|
||||
stdout, stderr, status = self.execute_command(nginx_cmd)
|
||||
|
||||
if not status:
|
||||
logger.error(f'Nginx konfigürasyon oluşturma hatası: {stderr}')
|
||||
raise Exception(f'Nginx konfigürasyonu oluşturulamadı: {stderr}')
|
||||
logger.info('Nginx konfigürasyonu başarıyla oluşturuldu')
|
||||
|
||||
# İzinleri ayarla
|
||||
logger.info('Nginx konfigürasyonu için izinler ayarlanıyor')
|
||||
self.execute_command(f'sudo chown root:root "{nginx_target}"')
|
||||
self.execute_command(f'sudo chmod 644 "{nginx_target}"')
|
||||
logger.info('Nginx konfigürasyonu için izinler başarıyla ayarlandı')
|
||||
|
||||
# Symbolic link oluştur
|
||||
logger.info('Nginx symbolic link oluşturuluyor')
|
||||
link_cmd = f'sudo ln -sf "{nginx_target}" "{nginx_enabled}"'
|
||||
stdout, stderr, status = self.execute_command(link_cmd)
|
||||
|
||||
if not status:
|
||||
logger.error(f'Nginx symbolic link oluşturma hatası: {stderr}')
|
||||
raise Exception(f'Nginx symbolic link oluşturulamadı: {stderr}')
|
||||
logger.info('Nginx symbolic link başarıyla oluşturuldu')
|
||||
|
||||
# Supervisor konfigürasyonunu direkt hedef konumunda oluştur
|
||||
logger.info('Supervisor konfigürasyonu ayarlanıyor')
|
||||
supervisor_target = f'/etc/supervisor/conf.d/{project.folder_name}.conf'
|
||||
|
||||
# Eski konfigürasyonu temizle
|
||||
logger.info('Eski Supervisor konfigürasyonu temizleniyor')
|
||||
self.execute_command(f'sudo rm -f {supervisor_target}')
|
||||
|
||||
# Yeni konfigürasyonu oluştur
|
||||
logger.info(f'Supervisor konfigürasyonu "{supervisor_target}" konumunda oluşturuluyor')
|
||||
supervisor_cmd = f'sudo bash -c \'cat > "{supervisor_target}" << "EOF"\n{configs["supervisor.conf"]}\nEOF\''
|
||||
stdout, stderr, status = self.execute_command(supervisor_cmd)
|
||||
|
||||
if not status:
|
||||
logger.error(f'Supervisor konfigürasyon oluşturma hatası: {stderr}')
|
||||
raise Exception(f'Supervisor konfigürasyonu oluşturulamadı: {stderr}')
|
||||
logger.info('Supervisor konfigürasyonu başarıyla oluşturuldu')
|
||||
|
||||
# İzinleri ayarla
|
||||
logger.info('Supervisor konfigürasyonu için izinler ayarlanıyor')
|
||||
self.execute_command(f'sudo chown root:root "{supervisor_target}"')
|
||||
self.execute_command(f'sudo chmod 644 "{supervisor_target}"')
|
||||
logger.info('Supervisor konfigürasyonu için izinler başarıyla ayarlandı')
|
||||
|
||||
# Servisleri yeniden yükle
|
||||
logger.info('Servisler yeniden başlatılıyor')
|
||||
self.execute_command('sudo systemctl reload nginx')
|
||||
self.execute_command('sudo supervisorctl reread')
|
||||
self.execute_command('sudo supervisorctl update')
|
||||
logger.info('Servisler başarıyla yeniden başlatıldı')
|
||||
|
||||
logger.info('Tüm konfigürasyon işlemleri başarıyla tamamlandı')
|
||||
return True, 'Konfigürasyon dosyaları başarıyla oluşturuldu ve konumlandırıldı'
|
||||
|
||||
except Exception as e:
|
||||
logger.error('Konfigürasyon dosyaları oluşturma hatası')
|
||||
logger.exception(e)
|
||||
return False, str(e)
|
||||
|
||||
def get_disk_usage(self):
|
||||
"""Sunucunun disk kullanım bilgilerini al"""
|
||||
try:
|
||||
# Ana disk bölümünün kullanım bilgilerini al (genellikle /)
|
||||
cmd = "df -h / | tail -n 1 | awk '{print $2,$3,$4,$5}'"
|
||||
stdout, stderr, status = self.execute_command(cmd)
|
||||
|
||||
if status:
|
||||
# Çıktıyı parçala: toplam, kullanılan, boş, yüzde
|
||||
parts = stdout.strip().split()
|
||||
if len(parts) == 4:
|
||||
# Yüzde işaretini kaldır ve sayıya çevir
|
||||
usage_percent = int(parts[3].replace('%', ''))
|
||||
return {
|
||||
'total': parts[0],
|
||||
'used': parts[1],
|
||||
'available': parts[2],
|
||||
'usage_percent': usage_percent
|
||||
}
|
||||
return None
|
||||
except Exception as e:
|
||||
logger.exception("Disk kullanım bilgisi alınamadı")
|
||||
return None
|
||||
|
||||
def upload_project_zip(self, project, zip_file):
|
||||
"""Proje dosyalarını yükle (zip veya txt)"""
|
||||
try:
|
||||
logger.info(f'"{project.folder_name}" projesi için dosya yükleme başlatıldı')
|
||||
|
||||
# Başlangıç disk kullanımını al
|
||||
initial_disk = self.get_disk_usage()
|
||||
if initial_disk:
|
||||
logger.info(f'Başlangıç disk kullanımı - Toplam: {initial_disk["total"]}, Kullanılan: {initial_disk["used"]}, Boş: {initial_disk["available"]}')
|
||||
|
||||
# Dosya uzantısını kontrol et
|
||||
file_extension = os.path.splitext(zip_file.name)[1].lower()
|
||||
|
||||
# Sadece zip ve txt dosyalarına izin ver
|
||||
if file_extension not in ['.zip', '.txt']:
|
||||
logger.warning(f'Geçersiz dosya uzantısı: {file_extension}')
|
||||
return False, "Sadece .zip ve .txt dosyaları yüklenebilir."
|
||||
|
||||
# Dosyayı yükle
|
||||
logger.info('SFTP bağlantısı açılıyor')
|
||||
sftp = self.client.open_sftp()
|
||||
|
||||
try:
|
||||
if file_extension == '.txt':
|
||||
# TXT dosyası ise direkt req.txt olarak kaydet
|
||||
remote_path = f"{project.get_full_path()}/req.txt"
|
||||
logger.info('TXT dosyası req.txt olarak yükleniyor')
|
||||
|
||||
# İlerleme için callback fonksiyonu
|
||||
total_size = zip_file.size
|
||||
uploaded_size = 0
|
||||
start_time = timezone.now()
|
||||
last_update = start_time
|
||||
|
||||
def progress_callback(sent_bytes, remaining_bytes):
|
||||
nonlocal uploaded_size, start_time, last_update
|
||||
uploaded_size = sent_bytes
|
||||
current_time = timezone.now()
|
||||
elapsed_time = (current_time - start_time).total_seconds()
|
||||
|
||||
# Her 0.5 saniyede bir güncelle
|
||||
if (current_time - last_update).total_seconds() >= 0.5:
|
||||
if elapsed_time > 0:
|
||||
speed = uploaded_size / elapsed_time # bytes/second
|
||||
percent = (uploaded_size / total_size) * 100
|
||||
remaining_size = total_size - uploaded_size
|
||||
eta = remaining_size / speed if speed > 0 else 0
|
||||
logger.info(f'Upload Progress: {percent:.1f}% - Speed: {speed/1024:.1f} KB/s - ETA: {eta:.1f}s')
|
||||
last_update = current_time
|
||||
|
||||
sftp.putfo(zip_file, remote_path, callback=progress_callback)
|
||||
logger.info('TXT dosyası başarıyla yüklendi')
|
||||
|
||||
# İzinleri ayarla
|
||||
self.execute_command(f'chmod 644 "{remote_path}"')
|
||||
|
||||
# Venv kontrolü yap
|
||||
logger.info('Virtual environment kontrol ediliyor')
|
||||
venv_exists = self.check_venv_exists(project)
|
||||
|
||||
if not venv_exists:
|
||||
# Venv oluştur
|
||||
logger.info('Virtual environment oluşturuluyor')
|
||||
venv_cmd = f'cd "{project.get_full_path()}" && python3 -m venv venv'
|
||||
stdout, stderr, status = self.execute_command(venv_cmd)
|
||||
if not status:
|
||||
error_msg = f'Venv oluşturma hatası: {stderr}'
|
||||
logger.error(error_msg)
|
||||
return False, stderr
|
||||
logger.info('Virtual environment başarıyla oluşturuldu')
|
||||
else:
|
||||
logger.info('Mevcut virtual environment kullanılacak')
|
||||
|
||||
# Requirements'ları kur
|
||||
logger.info('Requirements kuruluyor')
|
||||
install_cmd = f'''
|
||||
cd "{project.get_full_path()}" && \
|
||||
source venv/bin/activate && \
|
||||
pip install --upgrade pip 2>&1 && \
|
||||
pip install -r req.txt 2>&1
|
||||
'''
|
||||
stdout, stderr, status = self.execute_command(install_cmd)
|
||||
|
||||
if not status:
|
||||
# Pip çıktısını logla
|
||||
error_msg = 'Requirements kurulum hatası'
|
||||
logger.error(error_msg)
|
||||
logger.error(f'Pip çıktısı:\n{stdout}')
|
||||
if stderr:
|
||||
logger.error(f'Pip hata çıktısı:\n{stderr}')
|
||||
return False, stdout if stdout else stderr
|
||||
|
||||
# Başarılı pip çıktısını da logla
|
||||
logger.info('Requirements başarıyla kuruldu')
|
||||
logger.info(f'Pip kurulum çıktısı:\n{stdout}')
|
||||
return True, "Requirements dosyası yüklendi ve kuruldu"
|
||||
|
||||
else: # ZIP dosyası
|
||||
# Geçici dizin oluştur
|
||||
temp_dir = f'/tmp/project_upload_{project.id}'
|
||||
mkdir_cmd = f'rm -rf {temp_dir} && mkdir -p {temp_dir}'
|
||||
stdout, stderr, status = self.execute_command(mkdir_cmd)
|
||||
if not status:
|
||||
return False, f'Geçici dizin oluşturulamadı: {stderr}'
|
||||
|
||||
# ZIP dosyasını geçici dizine yükle
|
||||
remote_zip = f"{temp_dir}/upload.zip"
|
||||
logger.info(f'Zip dosyası "{remote_zip}" konumuna yükleniyor')
|
||||
|
||||
# İlerleme için callback fonksiyonu
|
||||
total_size = zip_file.size
|
||||
uploaded_size = 0
|
||||
start_time = timezone.now()
|
||||
last_update = start_time
|
||||
|
||||
def progress_callback(sent_bytes, remaining_bytes):
|
||||
nonlocal uploaded_size, start_time, last_update
|
||||
uploaded_size = sent_bytes
|
||||
current_time = timezone.now()
|
||||
elapsed_time = (current_time - start_time).total_seconds()
|
||||
|
||||
# Her 0.5 saniyede bir güncelle
|
||||
if (current_time - last_update).total_seconds() >= 0.5:
|
||||
if elapsed_time > 0:
|
||||
speed = uploaded_size / elapsed_time # bytes/second
|
||||
percent = (uploaded_size / total_size) * 100
|
||||
remaining_size = total_size - uploaded_size
|
||||
eta = remaining_size / speed if speed > 0 else 0
|
||||
logger.info(f'Upload Progress: {percent:.1f}% - Speed: {speed/1024:.1f} KB/s - ETA: {eta:.1f}s')
|
||||
last_update = current_time
|
||||
|
||||
sftp.putfo(zip_file, remote_zip, callback=progress_callback)
|
||||
logger.info('Zip dosyası başarıyla yüklendi')
|
||||
|
||||
# Zip dosyasını çıkart
|
||||
logger.info('Zip dosyası çıkartılıyor')
|
||||
unzip_cmd = f'''
|
||||
cd "{temp_dir}" && \
|
||||
unzip -o upload.zip && \
|
||||
rm upload.zip && \
|
||||
cp -rf * "{project.get_full_path()}/" && \
|
||||
cd / && \
|
||||
rm -rf "{temp_dir}"
|
||||
'''
|
||||
stdout, stderr, status = self.execute_command(unzip_cmd)
|
||||
|
||||
if not status:
|
||||
error_msg = f'Zip çıkartma hatası: {stderr}'
|
||||
logger.error(error_msg)
|
||||
return False, stderr
|
||||
|
||||
logger.info('Zip dosyası başarıyla çıkartıldı')
|
||||
|
||||
# req.txt var mı kontrol et
|
||||
logger.info('req.txt dosyası kontrol ediliyor')
|
||||
check_req = f'test -f "{project.get_full_path()}/req.txt" && echo "exists"'
|
||||
stdout, stderr, status = self.execute_command(check_req)
|
||||
|
||||
if status and stdout.strip() == "exists":
|
||||
logger.info('req.txt bulundu, venv kurulumu başlatılıyor')
|
||||
|
||||
# Venv kontrolü yap
|
||||
logger.info('Virtual environment kontrol ediliyor')
|
||||
venv_exists = self.check_venv_exists(project)
|
||||
|
||||
if not venv_exists:
|
||||
# Venv oluştur
|
||||
logger.info('Virtual environment oluşturuluyor')
|
||||
venv_cmd = f'cd "{project.get_full_path()}" && python3 -m venv venv'
|
||||
stdout, stderr, status = self.execute_command(venv_cmd)
|
||||
if not status:
|
||||
error_msg = f'Venv oluşturma hatası: {stderr}'
|
||||
logger.error(error_msg)
|
||||
return False, stderr
|
||||
logger.info('Virtual environment başarıyla oluşturuldu')
|
||||
else:
|
||||
logger.info('Mevcut virtual environment kullanılacak')
|
||||
|
||||
# Requirements'ları kur
|
||||
logger.info('Requirements kuruluyor')
|
||||
install_cmd = f'''
|
||||
cd "{project.get_full_path()}" && \
|
||||
source venv/bin/activate && \
|
||||
pip install --upgrade pip 2>&1 && \
|
||||
pip install -r req.txt 2>&1
|
||||
'''
|
||||
stdout, stderr, status = self.execute_command(install_cmd)
|
||||
|
||||
if not status:
|
||||
# Pip çıktısını logla
|
||||
error_msg = 'Requirements kurulum hatası'
|
||||
logger.error(error_msg)
|
||||
logger.error(f'Pip çıktısı:\n{stdout}')
|
||||
if stderr:
|
||||
logger.error(f'Pip hata çıktısı:\n{stderr}')
|
||||
return False, stdout if stdout else stderr
|
||||
|
||||
# Başarılı pip çıktısını da logla
|
||||
logger.info('Requirements başarıyla kuruldu')
|
||||
logger.info(f'Pip kurulum çıktısı:\n{stdout}')
|
||||
return True, "Proje dosyaları yüklendi ve requirements kuruldu"
|
||||
|
||||
return True, "Proje dosyaları başarıyla yüklendi"
|
||||
|
||||
finally:
|
||||
sftp.close()
|
||||
logger.info('SFTP bağlantısı kapatıldı')
|
||||
|
||||
# Son disk kullanımını al ve değişimi logla
|
||||
final_disk = self.get_disk_usage()
|
||||
if final_disk:
|
||||
logger.info(f'Son disk kullanımı - Toplam: {final_disk["total"]}, Kullanılan: {final_disk["used"]}, Boş: {final_disk["available"]}')
|
||||
|
||||
except Exception as e:
|
||||
logger.exception("Dosya yükleme hatası")
|
||||
return False, str(e)
|
||||
|
||||
def check_venv_exists(self, project):
|
||||
"""Virtual environment'ın var olup olmadığını kontrol et"""
|
||||
cmd = f'test -d "{project.get_full_path()}/venv" && echo "exists" || echo "not exists"'
|
||||
stdout, stderr, status = self.execute_command(cmd)
|
||||
return stdout.strip() == "exists"
|
||||
|
||||
def setup_venv_and_install_requirements(self, project):
|
||||
"""Virtual environment oluştur ve requirements'ları kur"""
|
||||
try:
|
||||
logger.info(f'"{project.folder_name}" projesi için venv oluşturuluyor')
|
||||
|
||||
# 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 = self.execute_command(check_cmd)
|
||||
|
||||
if stdout.strip() == "exists":
|
||||
logger.info('Mevcut venv kullanılacak')
|
||||
else:
|
||||
# Venv oluştur
|
||||
logger.info('Yeni venv oluşturuluyor')
|
||||
venv_cmd = f'cd "{project.get_full_path()}" && python3 -m venv venv'
|
||||
stdout, stderr, status = self.execute_command(venv_cmd)
|
||||
|
||||
if not status:
|
||||
logger.error(f'Venv oluşturma hatası: {stderr}')
|
||||
return False, f'Venv oluşturulamadı: {stderr}'
|
||||
|
||||
logger.info('Venv başarıyla oluşturuldu')
|
||||
|
||||
# pip'i güncelle ve requirements'ları kur
|
||||
logger.info('Requirements kuruluyor')
|
||||
install_cmd = f'''
|
||||
cd "{project.get_full_path()}" && \
|
||||
source venv/bin/activate && \
|
||||
pip install --upgrade pip && \
|
||||
pip install -r req.txt
|
||||
'''
|
||||
stdout, stderr, status = self.execute_command(install_cmd)
|
||||
|
||||
if not status:
|
||||
logger.error(f'Requirements kurulum hatası: {stderr}')
|
||||
return False, f'Requirements kurulamadı: {stderr}'
|
||||
|
||||
logger.info('Requirements başarıyla kuruldu')
|
||||
return True, "Venv oluşturuldu ve requirements kuruldu"
|
||||
|
||||
except Exception as e:
|
||||
logger.exception(f"Venv ve requirements kurulum hatası: {str(e)}")
|
||||
return False, str(e)
|
||||
|
||||
# SSHManager'ın tüm metodları buraya taşınacak...
|
||||
# utils.py'daki SSHManager sınıfının tüm içeriğini buraya kopyalayın
|
||||
Reference in New Issue
Block a user