mirror of
https://github.com/retspen/webvirtcloud
synced 2026-11-08 19:26:48 +00:00
The create forms of networks and storage pools checked the new name against the host's list of networks or pools, but that list holds one dict per object, so the name never matched and the check never fired; libvirt refused the duplicate with its own wording. The check now compares names: the page shows its own message, nothing is sent to libvirt, and the Logs page gets a failed row "...: add: name already in use".
293 lines
12 KiB
Python
293 lines
12 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 django.utils.translation import gettext_lazy as _
|
|
from libvirt import libvirtError
|
|
from logs.audit import audit, failed
|
|
from vrtManager.network import network_size, wvmNetwork, wvmNetworks
|
|
|
|
from networks.forms import AddNetPool
|
|
|
|
|
|
@superuser_only
|
|
def networks(request, compute_id):
|
|
"""
|
|
:param request:
|
|
:param compute_id:
|
|
:return:
|
|
"""
|
|
|
|
compute = get_object_or_404(Compute, pk=compute_id)
|
|
errors = False
|
|
|
|
try:
|
|
conn = wvmNetworks(
|
|
compute.hostname,
|
|
compute.login,
|
|
compute.password,
|
|
compute.type,
|
|
)
|
|
networks = conn.get_networks_info()
|
|
dhcp4 = netmask4 = gateway4 = ""
|
|
dhcp6 = prefix6 = gateway6 = ""
|
|
ipv4 = ipv6 = False
|
|
|
|
if request.method == "POST":
|
|
if "create" in request.POST:
|
|
form = AddNetPool(request.POST)
|
|
if form.is_valid():
|
|
data = form.cleaned_data
|
|
if data["name"] in [net["name"] for net in networks]:
|
|
msg = _("Network pool name already in use")
|
|
messages.error(request, msg)
|
|
failed(request, compute, f"Network {data['name']}", "add", "name already in use")
|
|
errors = True
|
|
if (
|
|
data["forward"] in ["bridge", "macvtap"]
|
|
and data["bridge_name"] == ""
|
|
):
|
|
messages.error(request, _("Please enter bridge/dev name"))
|
|
errors = True
|
|
if data["subnet"]:
|
|
ipv4 = True
|
|
gateway4, netmask4, dhcp4 = network_size(
|
|
data["subnet"], data["dhcp4"]
|
|
)
|
|
if data["subnet6"]:
|
|
ipv6 = True
|
|
gateway6, prefix6, dhcp6 = network_size(
|
|
data["subnet6"], data["dhcp6"]
|
|
)
|
|
if not errors:
|
|
with audit(request, compute, f"Network {data['name']}", "add"):
|
|
conn.create_network(
|
|
data["name"],
|
|
data["forward"],
|
|
ipv4,
|
|
gateway4,
|
|
netmask4,
|
|
dhcp4,
|
|
ipv6,
|
|
gateway6,
|
|
prefix6,
|
|
dhcp6,
|
|
data["bridge_name"],
|
|
data["openvswitch"],
|
|
data["fixed"],
|
|
)
|
|
return HttpResponseRedirect(
|
|
reverse("network", args=[compute_id, data["name"]])
|
|
)
|
|
else:
|
|
for msg_err in form.errors.values():
|
|
messages.error(request, msg_err.as_text())
|
|
conn.close()
|
|
except libvirtError as lib_err:
|
|
messages.error(request, lib_err)
|
|
|
|
return render(request, "networks.html", locals())
|
|
|
|
|
|
@superuser_only
|
|
def network(request, compute_id, pool):
|
|
"""
|
|
:param request:
|
|
:param compute_id:
|
|
:param pool:
|
|
:return:
|
|
"""
|
|
|
|
compute = get_object_or_404(Compute, pk=compute_id)
|
|
|
|
try:
|
|
conn = wvmNetwork(
|
|
compute.hostname,
|
|
compute.login,
|
|
compute.password,
|
|
compute.type,
|
|
pool,
|
|
)
|
|
networks = conn.get_networks()
|
|
state = conn.is_active()
|
|
device = conn.get_bridge_device()
|
|
autostart = conn.get_autostart()
|
|
net_mac = conn.get_network_mac()
|
|
net_forward = conn.get_network_forward()
|
|
qos = conn.get_qos()
|
|
dhcp_range_start = ipv4_dhcp_range_end = dict()
|
|
|
|
ip_networks = conn.get_ip_networks()
|
|
for family, ip_network in ip_networks.items():
|
|
if family == "ipv4":
|
|
ipv4_dhcp_range_start = conn.get_dhcp_range_start(family)
|
|
ipv4_dhcp_range_end = conn.get_dhcp_range_end(family)
|
|
ipv4_network = ip_network
|
|
ipv4_fixed_address = conn.get_dhcp_host_addr(family)
|
|
elif family == "ipv6":
|
|
ipv6_dhcp_range_start = conn.get_dhcp_range_start(family)
|
|
ipv6_dhcp_range_end = conn.get_dhcp_range_end(family)
|
|
ipv6_network = ip_network
|
|
ipv6_fixed_address = conn.get_dhcp_host_addr(family)
|
|
else:
|
|
raise Exception(_("Unknown Network Family"))
|
|
|
|
xml = conn._XMLDesc(0)
|
|
except libvirtError as lib_err:
|
|
messages.error(request, lib_err)
|
|
return HttpResponseRedirect(reverse("networks", args=[compute_id]))
|
|
|
|
if request.method == "POST":
|
|
subject = f"Network {pool}"
|
|
if "start" in request.POST:
|
|
try:
|
|
with audit(request, compute, subject, "start"):
|
|
conn.start()
|
|
return HttpResponseRedirect(request.get_full_path())
|
|
except libvirtError as lib_err:
|
|
messages.error(request, lib_err)
|
|
if "stop" in request.POST:
|
|
try:
|
|
with audit(request, compute, subject, "stop"):
|
|
conn.stop()
|
|
return HttpResponseRedirect(request.get_full_path())
|
|
except libvirtError as lib_err:
|
|
messages.error(request, lib_err)
|
|
if "delete" in request.POST:
|
|
try:
|
|
with audit(request, compute, subject, "delete"):
|
|
conn.delete()
|
|
return HttpResponseRedirect(reverse("networks", args=[compute_id]))
|
|
except libvirtError as lib_err:
|
|
messages.error(request, lib_err)
|
|
if "set_autostart" in request.POST:
|
|
try:
|
|
with audit(request, compute, subject, "autostart on"):
|
|
conn.set_autostart(1)
|
|
return HttpResponseRedirect(request.get_full_path())
|
|
except libvirtError as lib_err:
|
|
messages.error(request, lib_err)
|
|
if "unset_autostart" in request.POST:
|
|
try:
|
|
with audit(request, compute, subject, "autostart off"):
|
|
conn.set_autostart(0)
|
|
return HttpResponseRedirect(request.get_full_path())
|
|
except libvirtError as lib_err:
|
|
messages.error(request, lib_err)
|
|
if "modify_fixed_address" in request.POST:
|
|
name = request.POST.get("name", "")
|
|
address = request.POST.get("address", "")
|
|
family = request.POST.get("family", "ipv4")
|
|
|
|
if family == "ipv4":
|
|
mac_duid = request.POST.get("mac", "")
|
|
if family == "ipv6":
|
|
mac_duid = request.POST.get("id", "")
|
|
|
|
try:
|
|
with audit(request, compute, subject, f"set fixed address {address}"):
|
|
conn.modify_fixed_address(name, address, mac_duid, family)
|
|
messages.success(
|
|
request,
|
|
_("Fixed address operation completed for %(family)s")
|
|
% {"family": family.upper()},
|
|
)
|
|
return HttpResponseRedirect(request.get_full_path())
|
|
except libvirtError as lib_err:
|
|
messages.error(request, lib_err)
|
|
except ValueError as val_err:
|
|
messages.error(request, val_err)
|
|
if "delete_fixed_address" in request.POST:
|
|
ip = request.POST.get("address", "")
|
|
family = request.POST.get("family", "ipv4")
|
|
with audit(request, compute, subject, f"delete fixed address {ip}"):
|
|
conn.delete_fixed_address(ip, family)
|
|
messages.success(
|
|
request,
|
|
_("%(family)s Fixed Address is Deleted.") % {"family": family.upper()},
|
|
)
|
|
return HttpResponseRedirect(request.get_full_path())
|
|
if "modify_dhcp_range" in request.POST:
|
|
range_start = request.POST.get("range_start", "")
|
|
range_end = request.POST.get("range_end", "")
|
|
family = request.POST.get("family", "ipv4")
|
|
try:
|
|
with audit(request, compute, subject, f"set DHCP range {family.upper()}"):
|
|
conn.modify_dhcp_range(range_start, range_end, family)
|
|
messages.success(
|
|
request,
|
|
_("%(family)s DHCP Range is Changed.") % {"family": family.upper()},
|
|
)
|
|
return HttpResponseRedirect(request.get_full_path())
|
|
except libvirtError as lib_err:
|
|
messages.error(request, lib_err)
|
|
if "edit_network" in request.POST:
|
|
edit_xml = request.POST.get("edit_xml", "")
|
|
if edit_xml:
|
|
with audit(request, compute, subject, "change XML"):
|
|
conn.edit_network(edit_xml)
|
|
if conn.is_active():
|
|
messages.success(
|
|
request,
|
|
_(
|
|
"Network XML is changed. \\"
|
|
"Stop and start network to activate new config."
|
|
),
|
|
)
|
|
else:
|
|
messages.success(request, _("Network XML is changed."))
|
|
return HttpResponseRedirect(request.get_full_path())
|
|
if "set_qos" in request.POST:
|
|
qos_dir = request.POST.get("qos_direction", "")
|
|
average = request.POST.get("qos_average") or 0
|
|
peak = request.POST.get("qos_peak") or 0
|
|
burst = request.POST.get("qos_burst") or 0
|
|
|
|
try:
|
|
with audit(request, compute, subject, f"set QoS {qos_dir}"):
|
|
conn.set_qos(qos_dir, average, peak, burst)
|
|
if conn.is_active():
|
|
messages.success(
|
|
request,
|
|
_(
|
|
"%(qos_dir)s QoS is updated. Network XML is changed. Stop and start network to activate new config"
|
|
)
|
|
% {"qos_dir": qos_dir.capitalize()},
|
|
)
|
|
else:
|
|
messages.success(
|
|
request,
|
|
_("%(qos_dir)s QoS is set") % {"qos_dir": qos_dir.capitalize()},
|
|
)
|
|
except (libvirtError, ValueError) as err:
|
|
messages.error(request, err)
|
|
return HttpResponseRedirect(request.get_full_path())
|
|
if "unset_qos" in request.POST:
|
|
qos_dir = request.POST.get("qos_direction", "")
|
|
try:
|
|
with audit(request, compute, subject, f"unset QoS {qos_dir}"):
|
|
conn.unset_qos(qos_dir)
|
|
except ValueError as err:
|
|
messages.error(request, err)
|
|
return HttpResponseRedirect(request.get_full_path())
|
|
|
|
if conn.is_active():
|
|
messages.success(
|
|
request,
|
|
_(
|
|
"%(qos_dir)s QoS is deleted. Network XML is changed. \
|
|
Stop and start network to activate new config"
|
|
)
|
|
% {"qos_dir": qos_dir.capitalize()},
|
|
)
|
|
else:
|
|
messages.success(
|
|
request,
|
|
_("%(qos_dir)s QoS is deleted") % {"qos_dir": qos_dir.capitalize()},
|
|
)
|
|
return HttpResponseRedirect(request.get_full_path())
|
|
conn.close()
|
|
|
|
return render(request, "network.html", locals())
|