mirror of
https://github.com/retspen/webvirtcloud
synced 2025-03-23 05:23:00 +00:00
commit
8e4073f4b7
36 changed files with 16100 additions and 11347 deletions
README.md
accounts/templates
admin
appsettings/templates
computes
console/templates
doc/images
instances
locale
de/LC_MESSAGES
en/LC_MESSAGES
es/LC_MESSAGES
fr/LC_MESSAGES
nl/LC_MESSAGES
ru/LC_MESSAGES
tr/LC_MESSAGES
uk/LC_MESSAGES
networks
vrtManager
webvirtcloud
10
README.md
10
README.md
|
@ -335,13 +335,13 @@ python manage.py test
|
|||
|
||||
### Screenshots
|
||||
Instance Detail:
|
||||
<img src="doc/images/instance.PNG" width="95%" align="center"/>
|
||||
<img src="doc/images/instance.PNG" width="96%" align="center"/>
|
||||
Instance List:</br>
|
||||
<img src="doc/images/grouped.PNG" width="47%"/>
|
||||
<img src="doc/images/nongrouped.PNG" width="51%"/>
|
||||
<img src="doc/images/grouped.PNG" width="43%"/>
|
||||
<img src="doc/images/nongrouped.PNG" width="53%"/>
|
||||
Other: </br>
|
||||
<img src="doc/images/hosts.PNG" width="52%"/>
|
||||
<img src="doc/images/log.PNG" width="47%"/>
|
||||
<img src="doc/images/hosts.PNG" width="47%"/>
|
||||
<img src="doc/images/log.PNG" width="49%"/>
|
||||
|
||||
### License
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
<div class="col-lg-12">
|
||||
<h3 class="page-header">{% trans "Edit Profile" %}</h3>
|
||||
{% if perms.accounts.change_password %}
|
||||
<a href="{% url 'change_password' %}" class="btn btn-primary">{% icon 'lock' %} {% trans "Change Password" %}</a>
|
||||
<a href="{% url 'change_password' %}" class="ml-3 btn btn-primary">{% icon 'lock' %} {% trans "Change Password" %}</a>
|
||||
{% endif %}
|
||||
<form method="post" action="" role="form" aria-label="Edit user info form">{% csrf_token %}
|
||||
<div class="form-group">
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
from django import forms
|
||||
from django.contrib.auth.models import Group, User
|
||||
from django.contrib.auth.forms import ReadOnlyPasswordHashField
|
||||
from django.urls import reverse_lazy
|
||||
from django.utils.text import format_lazy
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from accounts.models import UserAttributes
|
||||
|
@ -68,6 +71,16 @@ class UserForm(forms.ModelForm):
|
|||
'is_superuser',
|
||||
]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(UserForm, self).__init__(*args, **kwargs)
|
||||
password = ReadOnlyPasswordHashField(label=_("Password"),
|
||||
help_text=format_lazy(_("""Raw passwords are not stored, so there is no way to see
|
||||
this user's password, but you can change the password
|
||||
using <a href='{}'>this form</a>."""),
|
||||
reverse_lazy('admin:user_update_password', args=[self.instance.id,]))
|
||||
)
|
||||
self.fields['Password'] = password
|
||||
|
||||
|
||||
class UserCreateForm(UserForm):
|
||||
password = forms.CharField(widget=forms.PasswordInput)
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
from django.urls import path
|
||||
from django.contrib.auth.views import PasswordChangeView, PasswordChangeDoneView
|
||||
|
||||
from . import views
|
||||
|
||||
|
@ -10,6 +9,7 @@ urlpatterns = [
|
|||
path('groups/<int:pk>/delete/', views.group_delete, name='group_delete'),
|
||||
path('users/', views.user_list, name='user_list'),
|
||||
path('users/create/', views.user_create, name='user_create'),
|
||||
path('users/<int:pk>/update_password/', views.user_update_password, name='user_update_password'),
|
||||
path('users/<int:pk>/update/', views.user_update, name='user_update'),
|
||||
path('users/<int:pk>/delete/', views.user_delete, name='user_delete'),
|
||||
path('users/<int:pk>/block/', views.user_block, name='user_block'),
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
from django.conf import settings
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth import update_session_auth_hash
|
||||
from django.contrib.auth.forms import AdminPasswordChangeForm
|
||||
from django.contrib.auth.models import Group, User
|
||||
from django.core.paginator import Paginator
|
||||
from django.shortcuts import get_object_or_404, redirect, render
|
||||
|
@ -133,6 +136,29 @@ def user_update(request, pk):
|
|||
},
|
||||
)
|
||||
|
||||
@superuser_only
|
||||
def user_update_password(request, pk):
|
||||
user = get_object_or_404(User, pk=pk)
|
||||
if request.method == 'POST':
|
||||
form = AdminPasswordChangeForm(user, request.POST)
|
||||
if form.is_valid():
|
||||
user = form.save()
|
||||
update_session_auth_hash(request, user) # Important!
|
||||
messages.success(request, _('User password changed: {}'.format(user.username)))
|
||||
return redirect('admin:user_list')
|
||||
else:
|
||||
messages.error(request, _('Wrong Data Provided'))
|
||||
else:
|
||||
form = AdminPasswordChangeForm(user)
|
||||
|
||||
return render(
|
||||
request,
|
||||
'accounts/change_password_form.html',
|
||||
{
|
||||
'form': form,
|
||||
'user': user.username
|
||||
}
|
||||
)
|
||||
|
||||
@superuser_only
|
||||
def user_delete(request, pk):
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
<!-- /.row -->
|
||||
|
||||
{% include 'errors_block.html' %}
|
||||
{% include 'messages_block.html' %}
|
||||
|
||||
<div class="">
|
||||
<div class="col-lg-12">
|
||||
|
|
|
@ -12,6 +12,7 @@ class TcpComputeForm(forms.ModelForm):
|
|||
|
||||
class Meta:
|
||||
model = Compute
|
||||
widgets = {'password': forms.PasswordInput()}
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
|
@ -30,6 +31,7 @@ class TlsComputeForm(forms.ModelForm):
|
|||
|
||||
class Meta:
|
||||
model = Compute
|
||||
widgets = {'password': forms.PasswordInput()}
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
|
|
|
@ -25,26 +25,26 @@
|
|||
<div class="col-lg-12">
|
||||
<table class="table table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th span="col">{% trans "Name" %}</th>
|
||||
<th span="col">{% trans "Status" %}</th>
|
||||
<th span="col">{% trans "Details" %}</th>
|
||||
<th span="col">{% trans "Actions" %}</th>
|
||||
<tr class="d-flex">
|
||||
<th span="col" class="col-sm-3">{% trans "Name" %}</th>
|
||||
<th span="col" class="col-sm-2">{% trans "Status" %}</th>
|
||||
<th span="col" class="col-sm-5">{% trans "Details" %}</th>
|
||||
<th span="col" class="col-sm-2 text-center">{% trans "Actions" %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="searchable">
|
||||
{% for compute in computes %}
|
||||
<tr>
|
||||
<td>
|
||||
<tr class="d-flex">
|
||||
<td class="col-sm-3">
|
||||
{{ compute.name }}
|
||||
</td>
|
||||
<td>
|
||||
<td class="col-sm-2">
|
||||
{% if compute.status is True %}{% trans "Connected" %}{% else %}{% trans "Not Connected" %}{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<td class="col-sm-5">
|
||||
{{ compute.details|default:"" }}
|
||||
</td>
|
||||
<td>
|
||||
<td class="col-sm-2">
|
||||
<div class="float-right btn-group">
|
||||
{% if compute.status is True %}
|
||||
<a class="btn btn-success" title="{%trans "Overview" %}" href="{% url 'overview' compute.id %}">{% icon 'eye' %}</a>
|
||||
|
|
|
@ -160,6 +160,11 @@
|
|||
SpiceHtml5.sendCtrlAltFN(sc, f);
|
||||
return false;
|
||||
}
|
||||
|
||||
function sendCtrlAltDel() {
|
||||
SpiceHtml5.sendCtrlAltDel(sc);
|
||||
return false;
|
||||
}
|
||||
/* SPICE port event listeners
|
||||
window.addEventListener('spice-port-data', function(event) {
|
||||
// Here we convert data to text, but really we can obtain binary data also
|
||||
|
|
|
@ -186,6 +186,11 @@
|
|||
return false;
|
||||
}
|
||||
|
||||
function sendCtrlAltDel() {
|
||||
SpiceHtml5.sendCtrlAltDel(sc);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* SPICE port event listeners
|
||||
window.addEventListener('spice-port-data', function(event) {
|
||||
// Here we convert data to text, but really we can obtain binary data also
|
||||
|
@ -198,7 +203,7 @@
|
|||
});
|
||||
*/
|
||||
document.getElementById("fullscreen_button").addEventListener('click', fullscreen);
|
||||
document.getElementById('ctrlaltdel').addEventListener('click', function () { sendCtrlAltDel(sc); });
|
||||
document.getElementById('ctrlaltdel').addEventListener('click', function () { sendCtrlAltDel(); });
|
||||
document.getElementById('ctrlaltf1').addEventListener('click', function () { sendctrlaltfn(0) });
|
||||
document.getElementById('ctrlaltf2').addEventListener('click', function () { sendctrlaltfn(1) });
|
||||
document.getElementById('ctrlaltf3').addEventListener('click', function () { sendctrlaltfn(2) });
|
||||
|
|
Binary file not shown.
Before (image error) Size: 27 KiB After (image error) Size: 32 KiB |
Binary file not shown.
Before (image error) Size: 20 KiB After (image error) Size: 22 KiB |
Binary file not shown.
Before (image error) Size: 20 KiB After (image error) Size: 20 KiB |
Binary file not shown.
Before (image error) Size: 32 KiB After (image error) Size: 28 KiB |
Binary file not shown.
Before (image error) Size: 25 KiB After (image error) Size: 24 KiB |
|
@ -12,6 +12,7 @@
|
|||
<!-- Tab panes -->
|
||||
<div class="tab-content">
|
||||
<div role="tabpanel" class="tab-pane tab-pane-bordered active" id="destroy">
|
||||
<p>{% trans 'This action starts remove instance process' %}</p>
|
||||
{% if request.user.is_superuser or userinstance.is_delete %}
|
||||
{% if instance.status == 3 %}
|
||||
<a class="btn btn-lg btn-success disabled float-right">{% trans "Destroy" %}</a>
|
||||
|
|
|
@ -353,6 +353,7 @@
|
|||
<input name="set_link_state" value="{{ network.state }}" hidden/>
|
||||
<input type="checkbox" {% if network.state == 'up' %} checked{% endif %} onclick='submit();' />
|
||||
<strong>{% trans 'active' %}</strong>
|
||||
<small>{{ network.type }}</small>
|
||||
</form>
|
||||
</td>
|
||||
<th class="d-none d-table-cell d-sm-table-cell">{% trans 'MAC' %}</th>
|
||||
|
@ -390,10 +391,10 @@
|
|||
<input class="form-control" type="text" value="{{ network.nic }}" readonly/>
|
||||
<select class="form-control" name="net-source-{{ forloop.counter0 }}">
|
||||
{% for c_net in networks_host %}
|
||||
<option value="net:{{ c_net }}" {% if c_net == network.nic %} selected {% endif %}>{% trans 'Network' %} {{ c_net }}</option>
|
||||
<option value="net:{{ c_net }}" {% if c_net == network.nic %} selected {% endif %}>{% trans 'Network' %} {{ c_net }}</option>
|
||||
{% endfor %}
|
||||
{% for c_iface in interfaces_host %}
|
||||
<option value="iface:{{ c_iface }}" {% if c_iface == network.nic %} selected {% endif %}>{% trans 'Interface' %} {{ c_iface }}</option>
|
||||
<option value="iface:{{ c_iface }}" {% if c_iface == network.nic %} selected {% endif %}>{% trans 'Interface' %} {{ c_iface }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
@ -405,7 +406,7 @@
|
|||
<select class="form-control" name="net-nwfilter-{{ forloop.counter0 }}">
|
||||
<option value="">{% trans "None" %}</option>
|
||||
{% for c_filters in nwfilters_host %}
|
||||
<option value="{{ c_filters }}" {% if c_filters == network.filterref %} selected {% endif %}>{{ c_filters }}</option>
|
||||
<option value="{{ c_filters }}" {% if c_filters == network.filterref %} selected {% endif %}>{{ c_filters }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
@ -462,7 +463,11 @@
|
|||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="bg-primary" colspan="9"></td>
|
||||
<td class="py-1 bg-primary text-white" colspan="9">
|
||||
{% if network.type == 'direct' %}
|
||||
<small>{% trans 'In most configurations, macvtap does not work for host to guest network communication' %}</small>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
|
|
|
@ -965,8 +965,8 @@ def set_qos(request, pk):
|
|||
else:
|
||||
messages.success(
|
||||
request,
|
||||
_(f"{qos_dir.capitalize()} QoS is set. Network XML is changed.") +
|
||||
_("Stop and start network to activate new config"),
|
||||
_(f"{qos_dir.capitalize()} QoS is set. Network XML is changed. \
|
||||
Stop and start network to activate new config.")
|
||||
)
|
||||
|
||||
return redirect(request.META.get('HTTP_REFERER') + '#network')
|
||||
|
@ -984,8 +984,8 @@ def unset_qos(request, pk):
|
|||
else:
|
||||
messages.success(
|
||||
request,
|
||||
_(f"{qos_dir.capitalize()} QoS is deleted. Network XML is changed. ") +
|
||||
_("Stop and start network to activate new config."),
|
||||
_(f"{qos_dir.capitalize()} QoS is deleted. Network XML is changed. \
|
||||
Stop and start network to activate new config.")
|
||||
)
|
||||
return redirect(request.META.get('HTTP_REFERER') + '#network')
|
||||
|
||||
|
@ -1409,7 +1409,7 @@ def create_instance(request, compute_id, arch, machine):
|
|||
console_pass=data["console_pass"],
|
||||
mac=data['mac'],
|
||||
qemu_ga=data['qemu_ga'])
|
||||
create_instance = Instance(compute_id=compute_id, name=data['name'])
|
||||
create_instance = Instance(compute_id=compute_id, name=data['name'], uuid=uuid)
|
||||
create_instance.save()
|
||||
msg = _("Instance is created")
|
||||
messages.success(request, msg)
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -46,7 +46,7 @@ class AddNetPool(forms.Form):
|
|||
|
||||
def clean_bridge_name(self):
|
||||
bridge_name = self.cleaned_data['bridge_name']
|
||||
if self.cleaned_data['forward'] == 'bridge':
|
||||
if self.cleaned_data['forward'] in ['bridge', 'macvtap']:
|
||||
have_symbol = re.match('^[a-zA-Z0-9\.\_\:\-]+$', bridge_name)
|
||||
if not have_symbol:
|
||||
raise forms.ValidationError(_('The pool bridge name must not contain any special characters'))
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
<option value="route">{% trans "ROUTE" %}</option>
|
||||
<option value="none">{% trans "ISOLATE" %}</option>
|
||||
<option value="bridge">{% trans "BRIDGE" %}</option>
|
||||
<option value="macvtap">{% trans "MACVTAP" %}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -55,25 +56,25 @@
|
|||
<input type="checkbox" id="enable_ipv6" name="enable_ipv6" value="false">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row bridge_name_form_group_dhcp ipv6_group">
|
||||
<div class="form-group row ipv6_group">
|
||||
<label class="col-sm-4 col-form-label">{% trans "IPv6 Subnet pool" %}</label>
|
||||
<div class="col-sm-6">
|
||||
<input type="text" class="form-control" name="subnet6" value="" placeholder="fd00:dead:baba:1::/64" required pattern="[0-9\/\.]+">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row bridge_name_form_group_dhcp ipv6_group">
|
||||
<div class="form-group row ipv6_group">
|
||||
<label class="col-sm-4 col-form-label">{% trans "DHCPv6" %}</label>
|
||||
<div class="col-sm-6">
|
||||
<input type="checkbox" name="dhcp6" value="true">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row bridge_name_form_group">
|
||||
<label class="col-sm-4 col-form-label">{% trans "Bridge Name" %}</label>
|
||||
<label class="col-sm-4 col-form-label" id="bridge_label">{% trans "Bridge Name" %}</label>
|
||||
<div class="col-sm-6">
|
||||
<input type="text" class="form-control" name="bridge_name" placeholder="br0" pattern="[a-z0-9\-_:]+">
|
||||
<input type="text" class="form-control" name="bridge_name" id="bridge_name" placeholder="br0" pattern="[a-z0-9\-_:]+">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row bridge_name_form_group">
|
||||
<div class="form-group row bridge_name_form_group openvswitch">
|
||||
<label class="col-sm-4 col-form-label">{% trans "Open vSwitch" %}</label>
|
||||
<div class="col-sm-6">
|
||||
<input type="checkbox" name="openvswitch" value="true">
|
||||
|
@ -88,4 +89,5 @@
|
|||
</div> <!-- /.modal-content -->
|
||||
</div> <!-- /.modal-dialog -->
|
||||
</div> <!-- /.modal -->
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
|
|
|
@ -37,7 +37,6 @@
|
|||
<!-- /.row -->
|
||||
|
||||
{% include 'errors_block.html' %}
|
||||
{% include 'messages_block.html' %}
|
||||
|
||||
<div class="row">
|
||||
<dl class="ml-3 row">
|
||||
|
|
|
@ -79,6 +79,12 @@
|
|||
if ($(this).val() == 'bridge') {
|
||||
$('.bridge_name_form_group').show();
|
||||
$('.bridge_name_form_group_dhcp').hide();
|
||||
} else if ($(this).val() == 'macvtap') {
|
||||
$('#bridge_label').text("Dev Name");
|
||||
$('#bridge_name').attr("placeholder", "eth0");
|
||||
$('.bridge_name_form_group').show();
|
||||
$('.bridge_name_form_group_dhcp').hide();
|
||||
$('.openvswitch').hide();
|
||||
} else {
|
||||
$('.bridge_name_form_group').hide();
|
||||
$('.bridge_name_form_group_dhcp').show();
|
||||
|
|
|
@ -42,8 +42,8 @@ def networks(request, compute_id):
|
|||
if data['name'] in networks:
|
||||
msg = _("Network pool name already in use")
|
||||
error_messages.append(msg)
|
||||
if data['forward'] == 'bridge' and data['bridge_name'] == '':
|
||||
error_messages.append(_('Please enter bridge name'))
|
||||
if data['forward'] in ['bridge', 'macvtap'] and data['bridge_name'] == '':
|
||||
error_messages.append(_('Please enter bridge/dev name'))
|
||||
if data['subnet']:
|
||||
ipv4 = True
|
||||
gateway4, netmask4, dhcp4 = network_size(data['subnet'], data['dhcp4'])
|
||||
|
|
|
@ -841,7 +841,7 @@ class wvmConnect(object):
|
|||
|
||||
def get_info(doc):
|
||||
mem = util.get_xpath(doc, "/domain/currentMemory")
|
||||
mem = int(mem) / 1024
|
||||
mem = int(mem) // 1024
|
||||
if raw_mem_size:
|
||||
mem = int(mem) * (1024 * 1024)
|
||||
cur_vcpu = util.get_xpath(doc, "/domain/vcpu/@current")
|
||||
|
@ -875,7 +875,7 @@ class wvmConnect(object):
|
|||
|
||||
def get_info(ctx):
|
||||
mem = util.get_xpath(ctx, "/domain/currentMemory")
|
||||
mem = int(mem) / 1024
|
||||
mem = int(mem) // 1024
|
||||
cur_vcpu = util.get_xpath(ctx, "/domain/vcpu/@current")
|
||||
if cur_vcpu:
|
||||
vcpu = cur_vcpu
|
||||
|
|
|
@ -32,7 +32,7 @@ class wvmInstances(wvmConnect):
|
|||
def get_instance_memory(self, name):
|
||||
inst = self.get_instance(name)
|
||||
mem = util.get_xml_path(inst.XMLDesc(0), "/domain/currentMemory")
|
||||
return int(mem) / 1024
|
||||
return int(mem) // 1024
|
||||
|
||||
def get_instance_vcpu(self, name):
|
||||
inst = self.get_instance(name)
|
||||
|
@ -242,11 +242,11 @@ class wvmInstance(wvmConnect):
|
|||
|
||||
def get_memory(self):
|
||||
mem = util.get_xml_path(self._XMLDesc(0), "/domain/memory")
|
||||
return int(mem) / 1024
|
||||
return int(mem) // 1024
|
||||
|
||||
def get_cur_memory(self):
|
||||
mem = util.get_xml_path(self._XMLDesc(0), "/domain/currentMemory")
|
||||
return int(mem) / 1024
|
||||
return int(mem) // 1024
|
||||
|
||||
def get_title(self):
|
||||
title = util.get_xml_path(self._XMLDesc(0), "/domain/title")
|
||||
|
@ -345,6 +345,7 @@ class wvmInstance(wvmConnect):
|
|||
result = []
|
||||
inbound = outbound = []
|
||||
for net in ctx.xpath('/domain/devices/interface'):
|
||||
interface_type = net.xpath('@type')[0]
|
||||
mac_inst = net.xpath('mac/@address')[0]
|
||||
nic_inst = net.xpath('source/@network|source/@bridge|source/@dev')[0]
|
||||
target_inst = '' if not net.xpath('target/@dev') else net.xpath('target/@dev')[0]
|
||||
|
@ -369,6 +370,7 @@ class wvmInstance(wvmConnect):
|
|||
except libvirtError:
|
||||
ipv4, ipv6 = None, None
|
||||
result.append({
|
||||
'type': interface_type,
|
||||
'mac': mac_inst,
|
||||
'nic': nic_inst,
|
||||
'target': target_inst,
|
||||
|
@ -993,7 +995,7 @@ class wvmInstance(wvmConnect):
|
|||
except SyntaxError:
|
||||
# Little fix for old version ElementTree
|
||||
graphic = root.find("devices/graphics")
|
||||
if keymap:
|
||||
if keymap != 'auto':
|
||||
graphic.set('keymap', keymap)
|
||||
else:
|
||||
try:
|
||||
|
@ -1289,24 +1291,39 @@ class wvmInstance(wvmConnect):
|
|||
bridge_name = iface.name()
|
||||
else:
|
||||
net = self.get_network(source)
|
||||
bridge_name = net.bridgeName()
|
||||
try:
|
||||
bridge_name = net.bridgeName()
|
||||
except libvirtError:
|
||||
bridge_name = None
|
||||
return bridge_name
|
||||
|
||||
def add_network(self, mac_address, source, source_type='net', model='virtio', nwfilter=None):
|
||||
bridge_name = self.get_bridge_name(source, source_type)
|
||||
forward_mode = ''
|
||||
if source_type != 'iface':
|
||||
forward_mode = self.get_network_forward(source)
|
||||
|
||||
forward_mode = self.get_network_forward(source)
|
||||
if forward_mode in ['nat', 'isolated', 'routed']:
|
||||
interface_type = 'network'
|
||||
elif forward_mode == '':
|
||||
interface_type = 'direct'
|
||||
else:
|
||||
interface_type = 'bridge'
|
||||
if self.get_bridge_name(source, source_type) is None:
|
||||
interface_type = 'network'
|
||||
else:
|
||||
interface_type = 'bridge'
|
||||
|
||||
xml_iface = f"""
|
||||
<interface type='{interface_type}'>
|
||||
<mac address='{mac_address}'/>"""
|
||||
if interface_type == 'network':
|
||||
xml_iface += f"""<source network='{source}'/>"""
|
||||
elif interface_type == 'direct':
|
||||
if source_type == 'net':
|
||||
xml_iface += f"""<source network='{source}' mode='bridge'/>"""
|
||||
else:
|
||||
xml_iface += f"""<source dev='{source}' mode='bridge'/>"""
|
||||
else:
|
||||
bridge_name = self.get_bridge_name(source, source_type)
|
||||
xml_iface += f"""<source bridge='{bridge_name}'/>"""
|
||||
xml_iface += f"""<model type='{model}'/>"""
|
||||
if nwfilter:
|
||||
|
@ -1342,49 +1359,38 @@ class wvmInstance(wvmConnect):
|
|||
net_source_type = network_data.get('net-source-' + str(num) + '-type')
|
||||
net_filter = network_data.get('net-nwfilter-' + str(num))
|
||||
net_model = network_data.get('net-model-' + str(num))
|
||||
bridge_name = self.get_bridge_name(net_source, net_source_type)
|
||||
|
||||
source = interface.find('source')
|
||||
if interface.get('type') == 'bridge':
|
||||
source = interface.find('mac')
|
||||
source.set('address', net_mac)
|
||||
source = interface.find('source')
|
||||
bridge_name = self.get_bridge_name(net_source, net_source_type)
|
||||
source.set('bridge', bridge_name)
|
||||
|
||||
source = interface.find('model')
|
||||
if net_model != 'default':
|
||||
source.attrib['type'] = net_model
|
||||
elif interface.get('type') in ['network', 'direct']:
|
||||
if net_source_type == 'net':
|
||||
source.set('network', net_source)
|
||||
elif net_source_type == 'iface':
|
||||
source.set('dev', net_source)
|
||||
else:
|
||||
interface.remove(source)
|
||||
raise libvirtError(f"Unknown network type: {net_source_type}")
|
||||
else:
|
||||
raise libvirtError(f"Unknown network type: {interface.get('type')}")
|
||||
|
||||
source = interface.find('filterref')
|
||||
if net_filter:
|
||||
if source is not None: source.set('filter', net_filter)
|
||||
else:
|
||||
element = ElementTree.Element("filterref")
|
||||
element.attrib['filter'] = net_filter
|
||||
interface.append(element)
|
||||
else:
|
||||
if source is not None: interface.remove(source)
|
||||
elif interface.get('type') == 'network':
|
||||
source = interface.find('mac')
|
||||
source.set('address', net_mac)
|
||||
source = interface.find('source')
|
||||
source.set('network', net_source)
|
||||
source = interface.find('model')
|
||||
if net_model != 'default':
|
||||
source.attrib['type'] = net_model
|
||||
else:
|
||||
interface.remove(source)
|
||||
|
||||
source = interface.find('model')
|
||||
if net_model != 'default':
|
||||
source.attrib['type'] = net_model
|
||||
source = interface.find('mac')
|
||||
source.set('address', net_mac)
|
||||
source = interface.find('filterref')
|
||||
if net_filter:
|
||||
if source is not None: source.set('filter', net_filter)
|
||||
else:
|
||||
interface.remove(source)
|
||||
|
||||
source = interface.find('filterref')
|
||||
if net_filter:
|
||||
if source is not None: source.set('filter', net_filter)
|
||||
else:
|
||||
element = ElementTree.Element("filterref")
|
||||
element.attrib['filter'] = net_filter
|
||||
interface.append(element)
|
||||
else:
|
||||
if source is not None: interface.remove(source)
|
||||
element = ElementTree.Element("filterref")
|
||||
element.attrib['filter'] = net_filter
|
||||
interface.append(element)
|
||||
else:
|
||||
if source is not None: interface.remove(source)
|
||||
|
||||
new_xml = ElementTree.tostring(tree).decode()
|
||||
self._defineXML(new_xml)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
from lxml import etree
|
||||
from libvirt import libvirtError
|
||||
from libvirt import VIR_NETWORK_SECTION_IP_DHCP_HOST
|
||||
from libvirt import VIR_NETWORK_UPDATE_COMMAND_ADD_LAST, VIR_NETWORK_UPDATE_COMMAND_DELETE, VIR_NETWORK_UPDATE_COMMAND_MODIFY
|
||||
from libvirt import VIR_NETWORK_UPDATE_AFFECT_LIVE, VIR_NETWORK_UPDATE_AFFECT_CONFIG
|
||||
|
@ -32,7 +33,11 @@ class wvmNetworks(wvmConnect):
|
|||
for network in get_networks:
|
||||
net = self.get_network(network)
|
||||
net_status = net.isActive()
|
||||
net_bridge = net.bridgeName()
|
||||
try:
|
||||
net_bridge = net.bridgeName()
|
||||
except libvirtError:
|
||||
net_bridge = util.get_xml_path(net.XMLDesc(0), "/network/forward/interface/@dev")
|
||||
|
||||
net_forward = util.get_xml_path(net.XMLDesc(0), "/network/forward/@mode")
|
||||
networks.append({'name': network, 'status': net_status,
|
||||
'device': net_bridge, 'forward': net_forward})
|
||||
|
@ -50,15 +55,20 @@ class wvmNetworks(wvmConnect):
|
|||
<name>{name}</name>"""
|
||||
if forward in ['nat', 'route', 'bridge']:
|
||||
xml += f"""<forward mode='{forward}'/>"""
|
||||
xml += """<bridge """
|
||||
if forward in ['nat', 'route', 'none']:
|
||||
xml += """stp='on' delay='0'"""
|
||||
if forward == 'bridge':
|
||||
xml += f"""name='{bridge}'"""
|
||||
xml += """/>"""
|
||||
if openvswitch is True:
|
||||
xml += """<virtualport type='openvswitch'/>"""
|
||||
if forward != 'bridge':
|
||||
if forward == 'macvtap':
|
||||
xml += f"""<forward mode='bridge'>
|
||||
<interface dev='{bridge}'/>
|
||||
</forward>"""
|
||||
else:
|
||||
xml += """<bridge """
|
||||
if forward in ['nat', 'route', 'none']:
|
||||
xml += """stp='on' delay='0'"""
|
||||
if forward == 'bridge':
|
||||
xml += f"""name='{bridge}'"""
|
||||
xml += """/>"""
|
||||
if openvswitch is True:
|
||||
xml += """<virtualport type='openvswitch'/>"""
|
||||
if forward not in ['bridge', 'macvtap']:
|
||||
if ipv4:
|
||||
xml += f"""<ip address='{gateway}' netmask='{mask}'>"""
|
||||
if dhcp4:
|
||||
|
@ -114,7 +124,7 @@ class wvmNetwork(wvmConnect):
|
|||
try:
|
||||
return self.net.bridgeName()
|
||||
except:
|
||||
return None
|
||||
return util.get_xml_path(self._XMLDesc(0), "/network/forward/interface/@dev")
|
||||
|
||||
def start(self):
|
||||
self.net.create()
|
||||
|
|
|
@ -19,8 +19,11 @@ urlpatterns = [
|
|||
]
|
||||
|
||||
if settings.DEBUG:
|
||||
import debug_toolbar
|
||||
try:
|
||||
import debug_toolbar
|
||||
|
||||
urlpatterns += [
|
||||
path('__debug__/', include(debug_toolbar.urls)),
|
||||
]
|
||||
urlpatterns += [
|
||||
path('__debug__/', include(debug_toolbar.urls)),
|
||||
]
|
||||
except:
|
||||
pass
|
||||
|
|
Loading…
Reference in a new issue