mirror of
https://github.com/retspen/webvirtcloud
synced 2026-11-08 19:26:48 +00:00
As the network and interface pages; plan reviewed with Codex. - The list is one table with a search: each filter's chain, priority, number of rules, the filters it references, and how many VMs and filters use it directly; a row's menu clones it (one shared dialog, the copy's name filled in) or deletes it, Delete disabled and saying so while it is in use. Without the VMs (a host that fails to list them) the list is not shown: it would offer to delete filters in use. - New filter is one dialog with the filter as XML in the Ace editor, from a starter filter, with what in, out and priority mean and a link to libvirt's format. - A filter's page: a Filter card (UUID, chain, priority, the VMs that use it directly, linked, and the filters that reference it, linked); its references with their parameters (one to a filter gone from the host marked as missing, not linked), removed per row, added from a select of the filters it can reference; its rules with the action as a badge, the direction as to or from the VM, the priority (500 where none is given), every protocol element with its attributes, a rule of no protocol as any traffic of the chain, and when it does not track connections; Add rule as an XML dialog; the XML, collapsed, saved in place. - The editors size themselves when shown and keep their label for screen readers; tables keep their hidden header text inside them, so a phone does not scroll the page sideways. add_nwf_rule.html goes (the dialog is on the page).
107 lines
5.2 KiB
Python
107 lines
5.2 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 instances.models import Instance
|
|
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())
|
|
|
|
# the VMs first: a list without them would offer to delete filters in use
|
|
users = conn.get_users()
|
|
nwfilters_all = conn.get_nwfilters_info()
|
|
for nwf in nwfilters_all:
|
|
nwf["vms"] = users.get(nwf["name"], [])
|
|
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()
|
|
chain = nwfilter.tree.get("chain")
|
|
priority = nwfilter.tree.get("priority")
|
|
rules = nwfilter.get_rules()
|
|
refs = nwfilter.get_refs()
|
|
ref_choices = nwfilter.get_ref_choices()
|
|
filter_names = nwfilter.get_nwfilters()
|
|
referenced_by = [nwf["name"] for nwf in nwfilter.get_nwfilters_info() if name in nwf["refs"]]
|
|
vm_names = nwfilter.get_users().get(name, [])
|
|
vm_ids = dict(Instance.objects.filter(compute=compute, name__in=vm_names).values_list("name", "id"))
|
|
vms = [{"name": vm_name, "id": vm_ids.get(vm_name)} for vm_name in vm_names]
|
|
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())
|