mirror of
https://github.com/retspen/webvirtcloud
synced 2026-11-11 12:46:49 +00:00
Plan reviewed with Codex; libvirt's behaviour checked on a host. - A filter is not deleted while a VM's interface references it, as the VM runs or as saved for its next boot (a stopped VM too), or while another filter references it: libvirt refuses only one a running VM uses, and a VM using a filter that references a deleted one does not start. The VMs are read from one listing, one or two XML reads each, instead of a connection per VM; the refusal names them. - Create refuses a name or UUID the host has, clone a name in use or one outside the panel's names, and editing the XML must keep the filter's name and UUID: each would replace another filter or make a copy. Entered XML is read for these checks without expanding entities or taking a DTD (util.parse_xml, shared with the network editor), and a rule is one <rule> element. - A rule or reference is deleted only while it reads as the page showed it, not by index and three attributes: a rule alike in those or a filter changed meanwhile loses nothing. - A reference is added only to another filter of the host not referenced yet; the picker offers those. - References keep their parameters, in order (a name may repeat); a rule shows every protocol element it has, a rule without one too. - One change a POST (two would both start from the page's reading, the second undoing the first); every change redirects and reports its refusal as a message, a POST for a filter gone meanwhile going to the list; the catch-all that showed any error goes, and so does wvmInstance.get_filterrefs, which only the old delete check used. The list reads each filter's XML once from one listing; a filter's page reads its XML once and only the other filters' names; the per-filter XML dialog of the list goes (a filter's page shows its XML). The XML editors send their text untouched too.
95 lines
4.5 KiB
Python
95 lines
4.5 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 django.urls import reverse
|
|
from libvirt import libvirtError
|
|
from logs.audit import audit
|
|
from vrtManager import util
|
|
from vrtManager.nwfilters import wvmNWFilter, wvmNWFilters
|
|
|
|
|
|
@superuser_only
|
|
def nwfilters(request, compute_id):
|
|
"""The host's network filters; one created, cloned or deleted, after
|
|
which the list is read again."""
|
|
compute = get_object_or_404(Compute, pk=compute_id)
|
|
nwfilters_all = []
|
|
|
|
try:
|
|
conn = wvmNWFilters(compute.hostname, compute.login, compute.password, compute.type)
|
|
|
|
if request.method == "POST":
|
|
name = request.POST.get("nwfiltername", "")
|
|
if "create_nwfilter" in request.POST:
|
|
xml = request.POST.get("nwfilter_xml", "")
|
|
try: # the row names the filter where the XML does
|
|
new_name = util.parse_xml(xml).get("name")
|
|
except util.OperationError:
|
|
new_name = None
|
|
with audit(request, compute, f"Network filter {new_name or '(no name)'}", "add"):
|
|
conn.create_nwfilter(xml)
|
|
elif "cln_nwfilter" in request.POST:
|
|
clone_name = request.POST.get("cln_name", "")
|
|
with audit(request, compute, f"Network filter {name}", f"clone as {clone_name}"):
|
|
conn.clone_nwfilter(name, clone_name)
|
|
elif "del_nwfilter" in request.POST:
|
|
with audit(request, compute, f"Network filter {name}", "delete"):
|
|
conn.delete_nwfilter(name)
|
|
return HttpResponseRedirect(request.get_full_path())
|
|
|
|
nwfilters_all = conn.get_nwfilters_info()
|
|
except libvirtError as lib_err: # OperationError too: a name in use, a filter in use
|
|
messages.error(request, lib_err)
|
|
if request.method == "POST": # a host not reached as well: nothing was changed
|
|
return HttpResponseRedirect(request.get_full_path())
|
|
|
|
return render(request, "nwfilters.html", {"nwfilters": nwfilters_all, "compute": compute})
|
|
|
|
|
|
@superuser_only
|
|
def nwfilter(request, compute_id, nwfltr):
|
|
"""A network filter of the host: its rules and references changed one at
|
|
a time, or its XML as a whole."""
|
|
compute = get_object_or_404(Compute, pk=compute_id)
|
|
|
|
try:
|
|
nwfilter = wvmNWFilter(compute.hostname, compute.login, compute.password, compute.type, nwfltr)
|
|
|
|
if request.method == "POST":
|
|
post = request.POST
|
|
subject = f"Network filter {nwfltr}"
|
|
try:
|
|
if "edit_nwfilter" in post:
|
|
with audit(request, compute, subject, "change XML"):
|
|
nwfilter.edit(post.get("edit_xml", ""))
|
|
elif "add_nwfilter_rule" in post:
|
|
with audit(request, compute, subject, "add rule"):
|
|
nwfilter.add_rule(post.get("nwfilterrule_xml", ""))
|
|
elif "del_nwfilter_rule" in post:
|
|
with audit(request, compute, subject, "delete rule"):
|
|
nwfilter.delete_rule(post.get("index", ""), post.get("rule", ""))
|
|
elif "add_nwfilter_ref" in post:
|
|
ref_name = post.get("nwfilters_select", "")
|
|
with audit(request, compute, subject, f"add reference {ref_name}"):
|
|
nwfilter.add_ref(ref_name)
|
|
elif "del_nwfilter_ref" in post:
|
|
with audit(request, compute, subject, "delete reference") as entry:
|
|
entry.action = f"delete reference {nwfilter.delete_ref(post.get('index', ''), post.get('ref', ''))}"
|
|
except libvirtError as err: # OperationError too: a filter changed meanwhile, XML refused
|
|
messages.error(request, err)
|
|
return HttpResponseRedirect(request.get_full_path())
|
|
|
|
name = nwfilter.get_name()
|
|
uuid = nwfilter.get_uuid()
|
|
xml = nwfilter.get_xml()
|
|
rules = nwfilter.get_rules()
|
|
refs = nwfilter.get_refs()
|
|
ref_choices = nwfilter.get_ref_choices()
|
|
except libvirtError as lib_err:
|
|
messages.error(request, lib_err)
|
|
if request.method == "POST": # a filter gone meanwhile, a host not reached: nothing was changed
|
|
return HttpResponseRedirect(reverse("nwfilters", args=[compute_id]))
|
|
|
|
return render(request, "nwfilter.html", locals())
|