2020-04-24 16:34:29 +00:00
|
|
|
import json
|
2021-12-06 05:42:50 +00:00
|
|
|
import os
|
2020-07-13 09:33:09 +00:00
|
|
|
|
2020-06-04 12:22:55 +00:00
|
|
|
from django.contrib import messages
|
2020-07-13 09:33:09 +00:00
|
|
|
from django.http import HttpResponse, HttpResponseRedirect
|
|
|
|
from django.shortcuts import get_object_or_404, redirect, render
|
2020-01-24 11:30:37 +00:00
|
|
|
from django.urls import reverse
|
2020-10-14 12:27:57 +00:00
|
|
|
from django.utils.translation import gettext_lazy as _
|
2020-06-04 12:22:55 +00:00
|
|
|
from libvirt import libvirtError
|
|
|
|
|
|
|
|
from admin.decorators import superuser_only
|
2020-07-13 09:33:09 +00:00
|
|
|
from appsettings.settings import app_settings
|
|
|
|
from computes.models import Compute
|
|
|
|
from storages.forms import AddStgPool, CloneImage, CreateVolumeForm
|
2015-02-27 09:28:22 +00:00
|
|
|
from vrtManager.storage import wvmStorage, wvmStorages
|
|
|
|
|
2019-09-10 06:48:31 +00:00
|
|
|
|
2020-05-27 12:24:06 +00:00
|
|
|
@superuser_only
|
2015-02-27 09:28:22 +00:00
|
|
|
def storages(request, compute_id):
|
|
|
|
"""
|
|
|
|
:param request:
|
2019-09-10 06:48:31 +00:00
|
|
|
:param compute_id:
|
2015-02-27 09:28:22 +00:00
|
|
|
:return:
|
|
|
|
"""
|
|
|
|
|
2015-04-02 12:39:40 +00:00
|
|
|
compute = get_object_or_404(Compute, pk=compute_id)
|
2020-10-15 14:18:45 +00:00
|
|
|
errors = False
|
2015-02-27 09:28:22 +00:00
|
|
|
|
|
|
|
try:
|
2020-05-27 12:24:06 +00:00
|
|
|
conn = wvmStorages(compute.hostname, compute.login, compute.password, compute.type)
|
2015-02-27 09:28:22 +00:00
|
|
|
storages = conn.get_storages_info()
|
|
|
|
secrets = conn.get_secrets()
|
|
|
|
|
2020-11-05 09:34:31 +00:00
|
|
|
if request.method == "POST":
|
|
|
|
if "create" in request.POST:
|
2015-02-27 09:28:22 +00:00
|
|
|
form = AddStgPool(request.POST)
|
|
|
|
if form.is_valid():
|
|
|
|
data = form.cleaned_data
|
2020-11-05 09:34:31 +00:00
|
|
|
if data["name"] in storages:
|
2015-02-27 09:28:22 +00:00
|
|
|
msg = _("Pool name already use")
|
2020-10-15 14:18:45 +00:00
|
|
|
messages.error(request, msg)
|
|
|
|
errors = True
|
2020-11-05 09:34:31 +00:00
|
|
|
if data["stg_type"] == "rbd":
|
|
|
|
if not data["secret"]:
|
2015-02-27 09:28:22 +00:00
|
|
|
msg = _("You need create secret for pool")
|
2020-10-15 14:18:45 +00:00
|
|
|
messages.error(request, msg)
|
|
|
|
errors = True
|
2020-11-05 09:34:31 +00:00
|
|
|
if not data["ceph_pool"] and not data["ceph_host"] and not data["ceph_user"]:
|
2015-02-27 09:28:22 +00:00
|
|
|
msg = _("You need input all fields for creating ceph pool")
|
2020-10-15 14:18:45 +00:00
|
|
|
messages.error(request, msg)
|
|
|
|
errors = True
|
|
|
|
if not errors:
|
2020-11-05 09:34:31 +00:00
|
|
|
if data["stg_type"] == "rbd":
|
|
|
|
conn.create_storage_ceph(
|
|
|
|
data["stg_type"],
|
|
|
|
data["name"],
|
|
|
|
data["ceph_pool"],
|
|
|
|
data["ceph_host"],
|
|
|
|
data["ceph_user"],
|
|
|
|
data["secret"],
|
|
|
|
)
|
|
|
|
elif data["stg_type"] == "netfs":
|
|
|
|
conn.create_storage_netfs(
|
|
|
|
data["stg_type"],
|
|
|
|
data["name"],
|
|
|
|
data["netfs_host"],
|
|
|
|
data["source"],
|
|
|
|
data["source_format"],
|
|
|
|
data["target"],
|
|
|
|
)
|
2015-02-27 09:28:22 +00:00
|
|
|
else:
|
2020-11-05 09:34:31 +00:00
|
|
|
conn.create_storage(data["stg_type"], data["name"], data["source"], data["target"])
|
|
|
|
return HttpResponseRedirect(reverse("storage", args=[compute_id, data["name"]]))
|
2015-03-10 14:24:10 +00:00
|
|
|
else:
|
|
|
|
for msg_err in form.errors.values():
|
2020-10-15 14:18:45 +00:00
|
|
|
messages.error(request, msg_err.as_text())
|
2015-02-27 09:28:22 +00:00
|
|
|
conn.close()
|
2015-02-27 09:51:33 +00:00
|
|
|
except libvirtError as lib_err:
|
2020-10-15 14:18:45 +00:00
|
|
|
messages.error(request, lib_err)
|
2015-02-27 09:28:22 +00:00
|
|
|
|
2020-11-05 09:34:31 +00:00
|
|
|
return render(request, "storages.html", locals())
|
2015-02-27 09:28:22 +00:00
|
|
|
|
|
|
|
|
2020-05-27 12:24:06 +00:00
|
|
|
@superuser_only
|
2015-02-27 09:28:22 +00:00
|
|
|
def storage(request, compute_id, pool):
|
|
|
|
"""
|
|
|
|
:param request:
|
2019-09-10 06:48:31 +00:00
|
|
|
:param compute_id:
|
|
|
|
:param pool:
|
2015-02-27 09:28:22 +00:00
|
|
|
:return:
|
|
|
|
"""
|
2020-11-05 09:34:31 +00:00
|
|
|
|
2015-02-27 09:28:22 +00:00
|
|
|
def handle_uploaded_file(path, f_name):
|
2021-12-17 06:21:42 +00:00
|
|
|
target = os.path.normpath(os.path.join(path, str(f_name)))
|
2021-12-06 05:42:50 +00:00
|
|
|
if not target.startswith(path):
|
2021-12-17 06:21:42 +00:00
|
|
|
raise Exception(_("Security Issues with file uploading"))
|
2021-12-06 05:42:50 +00:00
|
|
|
|
2021-12-17 06:21:42 +00:00
|
|
|
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"))
|
2015-02-27 09:28:22 +00:00
|
|
|
|
2015-04-02 12:39:40 +00:00
|
|
|
compute = get_object_or_404(Compute, pk=compute_id)
|
2015-02-27 09:28:22 +00:00
|
|
|
meta_prealloc = False
|
2020-07-13 09:33:09 +00:00
|
|
|
form = CreateVolumeForm()
|
|
|
|
|
|
|
|
conn = wvmStorage(compute.hostname, compute.login, compute.password, compute.type, pool)
|
|
|
|
|
|
|
|
storages = conn.get_storages()
|
|
|
|
state = conn.is_active()
|
|
|
|
size, free = conn.get_size()
|
2020-11-05 09:34:31 +00:00
|
|
|
used = size - free
|
2020-07-13 09:33:09 +00:00
|
|
|
if state:
|
|
|
|
percent = (used * 100) // size
|
|
|
|
else:
|
|
|
|
percent = 0
|
|
|
|
status = conn.get_status()
|
|
|
|
path = conn.get_target_path()
|
|
|
|
type = conn.get_type()
|
|
|
|
autostart = conn.get_autostart()
|
|
|
|
|
|
|
|
if state:
|
|
|
|
conn.refresh()
|
|
|
|
volumes = conn.update_volumes()
|
|
|
|
else:
|
|
|
|
volumes = None
|
2015-02-27 09:28:22 +00:00
|
|
|
|
2020-11-05 09:34:31 +00:00
|
|
|
if request.method == "POST":
|
|
|
|
if "start" in request.POST:
|
2020-07-13 09:33:09 +00:00
|
|
|
conn.start()
|
|
|
|
return HttpResponseRedirect(request.get_full_path())
|
2020-11-05 09:34:31 +00:00
|
|
|
if "stop" in request.POST:
|
2020-07-13 09:33:09 +00:00
|
|
|
conn.stop()
|
|
|
|
return HttpResponseRedirect(request.get_full_path())
|
2020-11-05 09:34:31 +00:00
|
|
|
if "delete" in request.POST:
|
2020-07-13 09:33:09 +00:00
|
|
|
conn.delete()
|
2020-11-05 09:34:31 +00:00
|
|
|
return HttpResponseRedirect(reverse("storages", args=[compute_id]))
|
|
|
|
if "set_autostart" in request.POST:
|
2020-07-13 09:33:09 +00:00
|
|
|
conn.set_autostart(1)
|
|
|
|
return HttpResponseRedirect(request.get_full_path())
|
2020-11-05 09:34:31 +00:00
|
|
|
if "unset_autostart" in request.POST:
|
2020-07-13 09:33:09 +00:00
|
|
|
conn.set_autostart(0)
|
|
|
|
return HttpResponseRedirect(request.get_full_path())
|
2020-11-05 09:34:31 +00:00
|
|
|
if "del_volume" in request.POST:
|
|
|
|
volname = request.POST.get("volname", "")
|
2020-07-13 09:33:09 +00:00
|
|
|
vol = conn.get_volume(volname)
|
|
|
|
vol.delete(0)
|
2021-12-16 08:03:03 +00:00
|
|
|
messages.success(request, _("Volume: %(vol)s is deleted.") % {"vol": volname})
|
2020-11-05 09:34:31 +00:00
|
|
|
return redirect(reverse("storage", args=[compute.id, pool]))
|
2020-07-13 09:33:09 +00:00
|
|
|
# return HttpResponseRedirect(request.get_full_path())
|
2020-11-05 09:34:31 +00:00
|
|
|
if "iso_upload" in request.POST:
|
|
|
|
if str(request.FILES["file"]) in conn.update_volumes():
|
2015-02-27 09:51:33 +00:00
|
|
|
error_msg = _("ISO image already exist")
|
2020-07-13 09:33:09 +00:00
|
|
|
messages.error(request, error_msg)
|
2015-02-27 09:28:22 +00:00
|
|
|
else:
|
2020-11-05 09:34:31 +00:00
|
|
|
handle_uploaded_file(path, request.FILES["file"])
|
|
|
|
messages.success(request, _("ISO: %(file)s is uploaded.") % {"file": request.FILES["file"]})
|
2015-02-27 09:28:22 +00:00
|
|
|
return HttpResponseRedirect(request.get_full_path())
|
2020-11-05 09:34:31 +00:00
|
|
|
if "cln_volume" in request.POST:
|
2015-02-27 09:28:22 +00:00
|
|
|
form = CloneImage(request.POST)
|
|
|
|
if form.is_valid():
|
|
|
|
data = form.cleaned_data
|
2020-11-05 09:34:31 +00:00
|
|
|
img_name = data["name"]
|
2015-02-27 09:28:22 +00:00
|
|
|
meta_prealloc = 0
|
|
|
|
if img_name in conn.update_volumes():
|
2019-04-29 11:10:54 +00:00
|
|
|
msg = _("Name of volume already in use")
|
2020-07-13 09:33:09 +00:00
|
|
|
messages.error(request, msg)
|
2020-11-05 09:34:31 +00:00
|
|
|
if data["convert"]:
|
|
|
|
format = data["format"]
|
|
|
|
if data["meta_prealloc"] and data["format"] == "qcow2":
|
2020-07-13 09:33:09 +00:00
|
|
|
meta_prealloc = True
|
|
|
|
else:
|
|
|
|
format = None
|
|
|
|
try:
|
2020-11-05 09:34:31 +00:00
|
|
|
name = conn.clone_volume(data["image"], data["name"], format, meta_prealloc)
|
|
|
|
messages.success(
|
|
|
|
request,
|
2021-10-04 13:18:36 +00:00
|
|
|
_("%(image)s image cloned as %(name)s successfully") % {"image": data["image"], "name": name},
|
2020-11-05 09:34:31 +00:00
|
|
|
)
|
2020-07-13 09:33:09 +00:00
|
|
|
return HttpResponseRedirect(request.get_full_path())
|
|
|
|
except libvirtError as lib_err:
|
|
|
|
messages.error(request, lib_err)
|
2015-03-10 14:24:10 +00:00
|
|
|
else:
|
|
|
|
for msg_err in form.errors.values():
|
2020-07-13 09:33:09 +00:00
|
|
|
messages.error(request, msg_err.as_text())
|
2018-10-24 09:04:05 +00:00
|
|
|
|
2015-02-27 09:28:22 +00:00
|
|
|
conn.close()
|
|
|
|
|
2020-11-05 09:34:31 +00:00
|
|
|
return render(request, "storage.html", locals())
|
2018-10-24 09:04:05 +00:00
|
|
|
|
2018-11-16 13:04:26 +00:00
|
|
|
|
2020-07-13 09:33:09 +00:00
|
|
|
@superuser_only
|
|
|
|
def create_volume(request, compute_id, pool):
|
2020-11-05 09:34:31 +00:00
|
|
|
"""
|
|
|
|
:param request:
|
|
|
|
:param compute_id: compute id
|
|
|
|
:param pool: pool name
|
|
|
|
:return:
|
|
|
|
"""
|
2020-07-13 09:33:09 +00:00
|
|
|
compute = get_object_or_404(Compute, pk=compute_id)
|
|
|
|
meta_prealloc = False
|
|
|
|
|
|
|
|
conn = wvmStorage(compute.hostname, compute.login, compute.password, compute.type, pool)
|
|
|
|
|
|
|
|
storages = conn.get_storages()
|
|
|
|
|
|
|
|
form = CreateVolumeForm(request.POST or None)
|
|
|
|
if form.is_valid():
|
|
|
|
data = form.cleaned_data
|
2020-11-05 09:34:31 +00:00
|
|
|
if data["meta_prealloc"] and data["format"] == "qcow2":
|
2020-07-13 09:33:09 +00:00
|
|
|
meta_prealloc = True
|
|
|
|
|
|
|
|
disk_owner_uid = int(app_settings.INSTANCE_VOLUME_DEFAULT_OWNER_UID)
|
|
|
|
disk_owner_gid = int(app_settings.INSTANCE_VOLUME_DEFAULT_OWNER_GID)
|
|
|
|
|
|
|
|
name = conn.create_volume(
|
2020-11-05 09:34:31 +00:00
|
|
|
data["name"],
|
|
|
|
data["size"],
|
|
|
|
data["format"],
|
2020-07-13 09:33:09 +00:00
|
|
|
meta_prealloc,
|
|
|
|
disk_owner_uid,
|
|
|
|
disk_owner_gid,
|
|
|
|
)
|
2020-11-05 09:34:31 +00:00
|
|
|
messages.success(request, _("Image file %(name)s is created successfully") % {"name": name})
|
2020-07-13 09:33:09 +00:00
|
|
|
else:
|
|
|
|
for msg_err in form.errors.values():
|
|
|
|
messages.error(request, msg_err.as_text())
|
|
|
|
|
2020-11-05 09:34:31 +00:00
|
|
|
return redirect(reverse("storage", args=[compute.id, pool]))
|
2020-07-13 09:33:09 +00:00
|
|
|
|
|
|
|
|
2018-11-16 13:04:26 +00:00
|
|
|
def get_volumes(request, compute_id, pool):
|
2020-04-24 16:34:29 +00:00
|
|
|
"""
|
|
|
|
:param request:
|
|
|
|
:param compute_id: compute id
|
|
|
|
:param pool: pool name
|
|
|
|
:return: volumes list of pool
|
|
|
|
"""
|
2018-11-16 13:04:26 +00:00
|
|
|
data = {}
|
|
|
|
compute = get_object_or_404(Compute, pk=compute_id)
|
|
|
|
try:
|
2020-05-27 12:24:06 +00:00
|
|
|
conn = wvmStorage(compute.hostname, compute.login, compute.password, compute.type, pool)
|
2018-12-03 13:18:41 +00:00
|
|
|
conn.refresh()
|
2020-11-05 09:34:31 +00:00
|
|
|
data["vols"] = sorted(conn.get_volumes())
|
2019-02-14 13:49:12 +00:00
|
|
|
except libvirtError:
|
2018-11-16 13:04:26 +00:00
|
|
|
pass
|
2019-09-10 06:48:31 +00:00
|
|
|
return HttpResponse(json.dumps(data))
|