1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2026-11-08 11:16:47 +00:00
webvirtcloud/virtsecrets/views.py
catborise 5b8793ad4c feat(logs): changes to networks, storage, interfaces, secrets and filters are logged
The Logs page now records every change an admin makes to a compute's
libvirt objects, with the compute's name in the host column:

- networks: add, start, stop, delete, autostart, DHCP range, fixed
  addresses, QoS and XML edits;
- storage pools: add, start, stop, delete, autostart, from web and
  API; volumes: add and delete (web and API), clone and ISO upload;
- host interfaces: add, start, stop, delete;
- secrets: add, set value (never the value), delete;
- network filters: add, clone, delete, XML edits, rules and
  references.

A refused or failed change is a failed row with its reason (libvirt
text through safe_text). The volume clone and upload jobs write their
row when they end; a refused submission is a failed row at once. A
volume row names the volume libvirt created (a dir pool adds .qcow2 or
.img). Volume create or delete through the API on an inactive pool
(409) is a failed row.

Network filters: the rows read "Network filter f1: add" instead of
"f1 network filter is created", and their host is the compute's name
instead of its hostname. A duplicate name or UUID no longer raises a
bare exception, and a filter XML that cannot be parsed no longer ends
in UnboundLocalError.
2026-10-23 13:30:21 +03:00

92 lines
3.4 KiB
Python

from admin.decorators import superuser_only
from computes.models import Compute
from django.contrib import messages
from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404, render
from libvirt import (
VIR_SECRET_USAGE_TYPE_CEPH,
VIR_SECRET_USAGE_TYPE_ISCSI,
VIR_SECRET_USAGE_TYPE_NONE,
VIR_SECRET_USAGE_TYPE_TLS,
VIR_SECRET_USAGE_TYPE_VOLUME,
libvirtError,
)
from logs.audit import audit
from vrtManager.util import OperationError
from vrtManager.virtsecrets import wvmSecrets
from virtsecrets.forms import AddSecret
@superuser_only
def secrets(request, compute_id):
"""
:param request:
:param compute_id:
:return:
"""
secrets_all = []
compute = get_object_or_404(Compute, pk=compute_id)
secret_usage_types = {
VIR_SECRET_USAGE_TYPE_NONE: "none",
VIR_SECRET_USAGE_TYPE_VOLUME: "volume",
VIR_SECRET_USAGE_TYPE_CEPH: "ceph",
VIR_SECRET_USAGE_TYPE_ISCSI: "iscsi",
VIR_SECRET_USAGE_TYPE_TLS: "tls",
}
# the create dialog offers the usage types the form takes
usage_choices = AddSecret.base_fields["usage_type"].choices
try:
conn = wvmSecrets(
compute.hostname, compute.login, compute.password, compute.type
)
secrets = conn.get_secrets()
for uuid in secrets:
secrt = conn.get_secret(uuid)
secrets_all.append(
{
"usage": secrt.usageID(),
"uuid": secrt.UUIDString(),
"usageType": secret_usage_types[secrt.usageType()],
}
)
if request.method == "POST":
if "create" in request.POST:
form = AddSecret(request.POST)
if form.is_valid():
data = form.cleaned_data
with audit(request, compute, f"Secret {data['usage_type']} {data['data']}", "add"):
conn.create_secret(
data["ephemeral"],
data["private"],
data["usage_type"],
data["data"],
)
return HttpResponseRedirect(request.get_full_path())
else:
for msg_err in form.errors.values():
messages.error(request, msg_err.as_text())
if "delete" in request.POST:
uuid = request.POST.get("uuid", "")
try:
with audit(request, compute, f"Secret {uuid}", "delete"):
conn.delete_secret(uuid)
except OperationError as err: # a VM disk or a pool needs it
messages.error(request, str(err))
return HttpResponseRedirect(request.get_full_path())
if "set_value" in request.POST:
uuid = request.POST.get("uuid", "")
value = request.POST.get("value", "")
try:
with audit(request, compute, f"Secret {uuid}", "set value"):
conn.set_secret_value(uuid, value)
except Exception as err:
messages.error(request, err)
return HttpResponseRedirect(request.get_full_path())
except libvirtError as err:
messages.error(request, err)
return render(request, "secrets.html", locals())