diff --git a/conf/requirements.txt b/conf/requirements.txt index a745a5c..be7b77b 100644 --- a/conf/requirements.txt +++ b/conf/requirements.txt @@ -15,7 +15,6 @@ libvirt-python==11.4.0 lxml==6.0.0 ldap3==2.9.1 markdown==3.8.2 -paramiko==3.4.0 #psycopg2-binary python-engineio==4.12.0 python-socketio==5.13.0 diff --git a/storages/templates/create_stg_vol_block.html b/storages/templates/create_stg_vol_block.html index 020b9c1..8da885e 100644 --- a/storages/templates/create_stg_vol_block.html +++ b/storages/templates/create_stg_vol_block.html @@ -16,27 +16,20 @@ -
{% csrf_token %} -
@@ -69,4 +62,4 @@ {% endif %} {% endif %} -{% endif %} +{% endif %} \ No newline at end of file diff --git a/storages/templates/storage.html b/storages/templates/storage.html index e4e726d..4b6235b 100644 --- a/storages/templates/storage.html +++ b/storages/templates/storage.html @@ -58,31 +58,32 @@
{{ used|filesizeformat }}
{% trans "State" %}
-
{% csrf_token %} + {% csrf_token %} {% if state == 0 %} - + {% else %} - + {% endif %}
{% trans "Autostart" %}
-
{% csrf_token %} + {% csrf_token %} {% if autostart == 0 %} {% else %} + onclick="return confirm('{% trans "Are you sure?" %}')" value="{% trans "Disable" %}"> {% endif %}
- {% if state %}

@@ -170,9 +171,9 @@ {% endif %} -

{% csrf_token %} + {% csrf_token %} -
@@ -215,80 +216,5 @@ $('.meta-prealloc').hide(); } }); - - $(document).ready(function() { - $('.confirm-form').on('submit', function(e) { - if (!confirm('{% trans "Are you sure?"|escapejs %}')) { - e.preventDefault(); - } - }); - - $('#isoUploadForm').on('submit', function(e) { - e.preventDefault(); - - var fileInput = $('#id_file')[0]; - if (fileInput.files.length === 0) { - alert("{% trans 'Please select a file to upload.'|escapejs %}"); - return; - } - - var file = fileInput.files[0]; - var fileName = file.name; - var chunkSize = 10 * 1024 * 1024; // 10MB - var totalChunks = Math.ceil(file.size / chunkSize); - var chunkIndex = 0; - - var progressBar = $('#upload-progress-bar'); - var progressContainer = $('#upload-progress-container'); - var errorMessage = $('#upload-error-message'); - - progressContainer.show(); - progressBar.width('0%').attr('aria-valuenow', 0).text('0%'); - errorMessage.hide(); - - function uploadChunk() { - if (chunkIndex >= totalChunks) { - return; - } - - var start = chunkIndex * chunkSize; - var end = Math.min(start + chunkSize, file.size); - var chunk = file.slice(start, end); - - var formData = new FormData(); - formData.append('file', chunk, fileName); - formData.append('file_name', fileName); - formData.append('chunk_index', chunkIndex); - formData.append('total_chunks', totalChunks); - formData.append('iso_upload', 'true'); - formData.append('csrfmiddlewaretoken', '{{ csrf_token }}'); - - $.ajax({ - url: "{% url 'storage' compute.id pool %}", - type: 'POST', - data: formData, - processData: false, - contentType: false, - success: function(data) { - chunkIndex++; - var percentComplete = Math.round((chunkIndex / totalChunks) * 100); - progressBar.width(percentComplete + '%').attr('aria-valuenow', percentComplete).text(percentComplete + '%'); - - if (data.reload) { - location.reload(); - } else if (chunkIndex < totalChunks) { - uploadChunk(); - } - }, - error: function(jqXHR, textStatus, errorThrown) { - var errorText = jqXHR.responseJSON && jqXHR.responseJSON.error ? jqXHR.responseJSON.error : "{% trans 'An error occurred during upload.'|escapejs %}"; - errorMessage.text(errorText).show(); - progressContainer.hide(); - } - }); - } - uploadChunk(); - }); - }); {% endblock %} diff --git a/storages/views.py b/storages/views.py index 0c9231e..a1690ec 100644 --- a/storages/views.py +++ b/storages/views.py @@ -5,14 +5,11 @@ from admin.decorators import superuser_only from appsettings.settings import app_settings from computes.models import Compute from django.contrib import messages -from django.http import HttpResponse, HttpResponseRedirect, JsonResponse +from django.http import HttpResponse, HttpResponseRedirect from django.shortcuts import get_object_or_404, redirect, render from django.urls import reverse from django.utils.translation import gettext_lazy as _ from libvirt import libvirtError -import paramiko - -from vrtManager.connection import CONN_SSH, CONN_SOCKET from vrtManager.storage import wvmStorage, wvmStorages from storages.forms import AddStgPool, CloneImage, CreateVolumeForm @@ -105,52 +102,20 @@ def storage(request, compute_id, pool): :param pool: :return: """ - def handle_uploaded_file(conn, path, file_name, file_chunk, is_last_chunk): - temp_name = f"{file_name}.part" - target_temp = os.path.normpath(os.path.join(path, temp_name)) - target_final = os.path.normpath(os.path.join(path, file_name)) - if not target_temp.startswith(path) or not target_final.startswith(path): + def handle_uploaded_file(path, f_name): + target = os.path.normpath(os.path.join(path, str(f_name))) + if not target.startswith(path): raise Exception(_("Security Issues with file uploading")) - if conn.conn == CONN_SSH: - try: - hostname, port = conn.host, 22 - if ":" in hostname: - hostname, port_str = hostname.split(":") - port = int(port_str) - - ssh = paramiko.SSHClient() - ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) - ssh.connect(hostname=hostname, port=port, username=conn.login, password=conn.passwd) - sftp = ssh.open_sftp() - - remote_file = sftp.open(target_temp, 'ab') - remote_file.set_pipelined(True) - for chunk_data in file_chunk.chunks(): - remote_file.write(chunk_data) - remote_file.close() - - if is_last_chunk: - sftp.rename(target_temp, target_final) - - sftp.close() - ssh.close() - except Exception as e: - raise Exception(_("SSH upload failed: {}").format(e)) - elif conn.conn == CONN_SOCKET: - try: - with open(target_temp, "ab") as f: - for chunk_data in file_chunk.chunks(): - f.write(chunk_data) - if is_last_chunk: - if os.path.exists(target_final): - os.remove(target_final) - os.rename(target_temp, target_final) - except FileNotFoundError: - raise Exception(_("File not found. Check the path variable and filename")) - else: - raise Exception(_("Unsupported connection type for file upload.")) + try: + with open(target, "wb+") as f: + for chunk in f_name.chunks(): + f.write(chunk) + except FileNotFoundError: + messages.error( + request, _("File not found. Check the path variable and filename") + ) compute = get_object_or_404(Compute, pk=compute_id) meta_prealloc = False @@ -162,16 +127,12 @@ def storage(request, compute_id, pool): storages = conn.get_storages() state = conn.is_active() - try: - size, free = conn.get_size() - used = size - free - if state: - percent = (used * 100) // size - else: - percent = 0 - except libvirtError: - size, free, used, percent = 0, 0, 0, 0 - + size, free = conn.get_size() + used = size - free + if state: + percent = (used * 100) // size + else: + percent = 0 status = conn.get_status() path = conn.get_target_path() type = conn.get_type() @@ -209,56 +170,16 @@ def storage(request, compute_id, pool): return redirect(reverse("storage", args=[compute.id, pool])) # return HttpResponseRedirect(request.get_full_path()) if "iso_upload" in request.POST: - file_chunk = request.FILES.get("file") - if not file_chunk: - return JsonResponse({"error": _("No file chunk was submitted.")}, status=400) - - file_name = request.POST.get("file_name") - chunk_index = int(request.POST.get("chunk_index", 0)) - total_chunks = int(request.POST.get("total_chunks", 1)) - is_last_chunk = chunk_index == total_chunks - 1 - - # On first chunk, check if file already exists - if chunk_index == 0: - if file_name in conn.get_volumes(): - return JsonResponse({"error": _("ISO image already exists")}, status=400) - # Clean up any partial files from previous failed uploads - temp_part_file = os.path.normpath(os.path.join(path, f"{file_name}.part")) - if conn.conn == CONN_SOCKET and os.path.exists(temp_part_file): - os.remove(temp_part_file) - elif conn.conn == CONN_SSH: - try: - hostname, port = conn.host, 22 - if ":" in hostname: - hostname, port_str = hostname.split(":") - port = int(port_str) - ssh = paramiko.SSHClient() - ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) - ssh.connect(hostname=hostname, port=port, username=conn.login, password=conn.passwd) - sftp = ssh.open_sftp() - try: - sftp.remove(temp_part_file) - except FileNotFoundError: - pass # File doesn't exist, which is fine - sftp.close() - ssh.close() - except Exception: - # Best effort to clean up, if it fails, let it be. - pass - - try: - handle_uploaded_file(conn, path, file_name, file_chunk, is_last_chunk) - - if is_last_chunk: - success_msg = _("ISO: %(file)s has been uploaded successfully.") % {"file": file_name} - messages.success(request, success_msg) - return JsonResponse({"success": True, "message": success_msg, "reload": True}) - else: - return JsonResponse({"success": True, "message": "Chunk received."}) - except Exception as e: - error_msg = str(e) + if str(request.FILES["file"]) in conn.update_volumes(): + error_msg = _("ISO image already exist") messages.error(request, error_msg) - return JsonResponse({"error": error_msg}, status=500) + else: + handle_uploaded_file(path, request.FILES["file"]) + messages.success( + request, + _("ISO: %(file)s is uploaded.") % {"file": request.FILES["file"]}, + ) + return HttpResponseRedirect(request.get_full_path()) if "cln_volume" in request.POST: form = CloneImage(request.POST) if form.is_valid():