Commit 2ada70e6 by Kálmán Viktor

network: add switch port management

parent 0eb6f901
...@@ -756,6 +756,10 @@ class SwitchPort(models.Model): ...@@ -756,6 +756,10 @@ class SwitchPort(models.Model):
self.untagged_vlan, self.untagged_vlan,
tagged_vlans) tagged_vlans)
@models.permalink
def get_absolute_url(self):
return ('network.switch_port', None, {'pk': self.pk})
class EthernetDevice(models.Model): class EthernetDevice(models.Model):
name = models.CharField(max_length=20, name = models.CharField(max_length=20,
......
...@@ -6,7 +6,7 @@ from crispy_forms.layout import Layout, Fieldset, Div, Submit, BaseInput ...@@ -6,7 +6,7 @@ from crispy_forms.layout import Layout, Fieldset, Div, Submit, BaseInput
from crispy_forms.bootstrap import FormActions from crispy_forms.bootstrap import FormActions
from firewall.models import (Host, Vlan, Domain, Group, Record, Blacklist, from firewall.models import (Host, Vlan, Domain, Group, Record, Blacklist,
Rule, VlanGroup) Rule, VlanGroup, SwitchPort)
class LinkButton(BaseInput): class LinkButton(BaseInput):
...@@ -188,6 +188,28 @@ class RuleForm(ModelForm): ...@@ -188,6 +188,28 @@ class RuleForm(ModelForm):
model = Rule model = Rule
class SwitchPortForm(ModelForm):
helper = FormHelper()
helper.layout = Layout(
Div(
Fieldset(
'',
'untagged_vlan',
'tagged_vlans',
'description',
)
),
FormActions(
Submit('submit', 'Save'),
LinkButton('back', 'Back',
reverse_lazy('network.switch_port_list'))
)
)
class Meta:
model = SwitchPort
class VlanForm(ModelForm): class VlanForm(ModelForm):
helper = FormHelper() helper = FormHelper()
helper.layout = Layout( helper.layout = Layout(
......
$('i[class="icon-remove"]').click(function() {
href = $(this).parent('a').attr('href');
csrf = getCookie('csrftoken');
var click_this = this;
group = $(this).closest('h4').text();
s = gettext('Are you sure you want to delete this device?');
bootbox.dialog({
message: s,
buttons: {
cancel: {
'label': gettext("Cancel"),
'className': "btn-info",
'callback': function () {}
},
remove: {
'label': gettext("Remove"),
'className': "btn-danger",
'callback': function() {
delete_device(click_this);
}
}
}
});
return false;
});
function delete_device(click_this) {
ajax = $.ajax({
type: 'POST',
url: href,
headers: {"X-CSRFToken": csrf},
context: click_this,
success: function(data, textStatus, xhr) {
if(xhr.status == 200) {
$(this).closest('tr').fadeOut(500, function() {
$(this).remove();
});
}
}
});
return false;
}
from django_tables2 import Table, A from django_tables2 import Table, A
from django_tables2.columns import LinkColumn, TemplateColumn from django_tables2.columns import LinkColumn, TemplateColumn
from firewall.models import Host, Vlan, Domain, Group, Record, Rule from firewall.models import Host, Vlan, Domain, Group, Record, Rule, SwitchPort
class BlacklistTable(Table): class BlacklistTable(Table):
...@@ -129,6 +129,17 @@ class RuleTable(Table): ...@@ -129,6 +129,17 @@ class RuleTable(Table):
order_by = 'direction' order_by = 'direction'
class SwitchPortTable(Table):
pk = LinkColumn('network.switch_port', args=[A('pk')],
verbose_name="ID")
class Meta:
model = SwitchPort
attrs = {'class': 'table table-striped table-condensed'}
fields = ('pk', 'untagged_vlan', 'tagged_vlans', 'description', )
order_by = 'pk'
class VlanTable(Table): class VlanTable(Table):
name = LinkColumn('network.vlan', args=[A('vid')]) name = LinkColumn('network.vlan', args=[A('vid')])
......
...@@ -19,6 +19,9 @@ ...@@ -19,6 +19,9 @@
{% url "network.rule_list" as u %} {% url "network.rule_list" as u %}
{% trans "Rules" as t %} {% trans "Rules" as t %}
{% include "network/menu-item.html" with href=u text=t %} {% include "network/menu-item.html" with href=u text=t %}
{% url "network.switch_port_list" as u %}
{% trans "Switch ports" as t %}
{% include "network/menu-item.html" with href=u text=t %}
<li class="dropdown{% if "groups" in request.path %} active{% endif %}"> <li class="dropdown{% if "groups" in request.path %} active{% endif %}">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Groups <b class="caret"></b></a> <a href="#" class="dropdown-toggle" data-toggle="dropdown">Groups <b class="caret"></b></a>
......
{% extends "network/base.html" %}
{% load render_table from django_tables2 %}
{% load i18n %}
{% load l10n %}
{% load staticfiles %}
{% load crispy_forms_tags %}
{% block content %}
<div class="page-header">
<h2>{% trans "Create a new switch port" %}</h2>
</div>
<div class="row">
<div class="col-sm-8">
{% crispy form %}
</div>
<div class="col-sm-4">
Halp
</div>
</div>
{% endblock %}
{% extends "network/base.html" %}
{% load render_table from django_tables2 %}
{% load i18n %}
{% load l10n %}
{% load staticfiles %}
{% load crispy_forms_tags %}
{% block content %}
<div class="page-header">
<a href="{% url "network.switch_port_delete" pk=switch_port_pk %}" class="btn btn-danger pull-right"><i class="icon-remove-sign"></i> {% trans "Delete this switchport" %}</a>
<h2>Welp <small>dunno what to write here</small></h2>
</div>
<div class="row">
<div class="col-sm-5">
{% crispy form %}
</div>
<style>
.ethernet-devices-mini-table tr td:last-child {
width: 1px;
}
</style>
<div class="col-sm-5 col-sm-offset-1">
<h3>{% trans "Ethernet Devices" %}</h3>
<hr />
{% if devices %}
<table class="table table-condensed table-bordered ethernet-devices-mini-table">
{% for i in devices %}
<tr>
<td>{{ i }}</td>
<td>
<a href="{% url "network.remove_switch_port_device" pk=switch_port_pk device_pk=i.pk %}"><i class="icon-remove"></i></a>
</td>
</tr>
{% endfor %}
</table>
{% else %}
{% trans "No ethernet device" %}
{% endif %}
<hr />
<form action="{% url "network.add_switch_port_device" pk=switch_port_pk %}" method="POST">
{% csrf_token %}
<div class="input-group">
<input type="text" class="form-control" name="device_name" placeholder="{% trans "Name" %}"/>
<div class="input-group-btn">
<input type="submit" value="{% trans "Add new Ethernet Device" %}" class="btn btn-default"></input>
</div>
</div><!-- input-group -->
</form>
</div>
</div>
{% endblock %}
{% block extra_etc %}
<script src="{% static "js/switch-port.js" %}"></script>
{% endblock %}
{% extends "network/base.html" %}
{% load render_table from django_tables2 %}
{% load i18n %}
{% load l10n %}
{% load staticfiles %}
{% block content %}
<div class="page-header">
<a href="{% url "network.switch_port_create" %}" class="btn btn-success pull-right"><i class="icon-plus-sign"></i> {% trans "Create a new switch port" %}</a>
<h1>{% trans "Switch ports" %} <small></small></h1>
</div>
<div class="table-responsive">
{% render_table table %}
</div>
{% endblock %}
...@@ -8,9 +8,12 @@ from .views import (IndexView, ...@@ -8,9 +8,12 @@ from .views import (IndexView,
BlacklistList, BlacklistDetail, BlacklistDelete, BlacklistList, BlacklistDetail, BlacklistDelete,
BlacklistCreate, BlacklistCreate,
RuleList, RuleDetail, RuleDelete, RuleCreate, RuleList, RuleDetail, RuleDelete, RuleCreate,
SwitchPortList, SwitchPortDetail, SwitchPortCreate,
SwitchPortDelete,
VlanGroupList, VlanGroupDetail, VlanGroupDelete, VlanGroupList, VlanGroupDetail, VlanGroupDelete,
VlanGroupCreate, VlanGroupCreate,
remove_host_group, add_host_group) remove_host_group, add_host_group,
remove_switch_port_device, add_switch_port_device)
js_info_dict = { js_info_dict = {
'packages': ('network', ), 'packages': ('network', ),
...@@ -56,6 +59,14 @@ urlpatterns = patterns( ...@@ -56,6 +59,14 @@ urlpatterns = patterns(
url('^rules/create$', RuleCreate.as_view(), name='network.rule_create'), url('^rules/create$', RuleCreate.as_view(), name='network.rule_create'),
url('^rules/(?P<pk>\d+)/$', RuleDetail.as_view(), url('^rules/(?P<pk>\d+)/$', RuleDetail.as_view(),
name='network.rule'), name='network.rule'),
url('^switchports/$', SwitchPortList.as_view(),
name='network.switch_port_list'),
url('^switchports/create$', SwitchPortCreate.as_view(),
name='network.switch_port_create'),
url('^switchports/(?P<pk>\d+)/$', SwitchPortDetail.as_view(),
name='network.switch_port'),
url('^switchports/delete/(?P<pk>\d+)/$', SwitchPortDelete.as_view(),
name="network.switch_port_delete"),
url('^vlans/$', VlanList.as_view(), name='network.vlan_list'), url('^vlans/$', VlanList.as_view(), name='network.vlan_list'),
url('^vlans/create$', VlanCreate.as_view(), name='network.vlan_create'), url('^vlans/create$', VlanCreate.as_view(), name='network.vlan_create'),
url('^vlans/(?P<vid>\d+)/$', VlanDetail.as_view(), name='network.vlan'), url('^vlans/(?P<vid>\d+)/$', VlanDetail.as_view(), name='network.vlan'),
...@@ -71,10 +82,18 @@ urlpatterns = patterns( ...@@ -71,10 +82,18 @@ urlpatterns = patterns(
name="network.vlan_group_delete"), name="network.vlan_group_delete"),
url('^rules/delete/(?P<pk>\d+)/$', RuleDelete.as_view(), url('^rules/delete/(?P<pk>\d+)/$', RuleDelete.as_view(),
name="network.rule_delete"), name="network.rule_delete"),
# non class based views
url('^hosts/(?P<pk>\d+)/remove/(?P<group_pk>\d+)/$', remove_host_group, url('^hosts/(?P<pk>\d+)/remove/(?P<group_pk>\d+)/$', remove_host_group,
name='network.remove_host_group'), name='network.remove_host_group'),
url('^hosts/(?P<pk>\d+)/add/$', add_host_group, url('^hosts/(?P<pk>\d+)/add/$', add_host_group,
name='network.add_host_group'), name='network.add_host_group'),
url('^switchports/(?P<pk>\d+)/remove/(?P<device_pk>\d+)/$',
remove_switch_port_device, name='network.remove_switch_port_device'),
url('^switchports/(?P<pk>\d+)/add/$', add_switch_port_device,
name='network.add_switch_port_device'),
# js gettext catalog
url(r'^jsi18n/$', 'django.views.i18n.javascript_catalog', js_info_dict, url(r'^jsi18n/$', 'django.views.i18n.javascript_catalog', js_info_dict,
name="network.js_catalog"), name="network.js_catalog"),
) )
...@@ -7,13 +7,13 @@ from django.http import HttpResponse ...@@ -7,13 +7,13 @@ from django.http import HttpResponse
from django_tables2 import SingleTableView from django_tables2 import SingleTableView
from firewall.models import (Host, Vlan, Domain, Group, Record, Blacklist, from firewall.models import (Host, Vlan, Domain, Group, Record, Blacklist,
Rule, VlanGroup) Rule, VlanGroup, SwitchPort, EthernetDevice)
from .tables import (HostTable, VlanTable, SmallHostTable, DomainTable, from .tables import (HostTable, VlanTable, SmallHostTable, DomainTable,
GroupTable, RecordTable, BlacklistTable, RuleTable, GroupTable, RecordTable, BlacklistTable, RuleTable,
VlanGroupTable, SmallRuleTable, SmallGroupRuleTable, VlanGroupTable, SmallRuleTable, SmallGroupRuleTable,
SmallRecordTable) SmallRecordTable, SwitchPortTable)
from .forms import (HostForm, VlanForm, DomainForm, GroupForm, RecordForm, from .forms import (HostForm, VlanForm, DomainForm, GroupForm, RecordForm,
BlacklistForm, RuleForm, VlanGroupForm) BlacklistForm, RuleForm, VlanGroupForm, SwitchPortForm)
from django.contrib import messages from django.contrib import messages
from django.views.generic.edit import FormMixin from django.views.generic.edit import FormMixin
...@@ -530,6 +530,50 @@ class RuleDelete(DeleteView): ...@@ -530,6 +530,50 @@ class RuleDelete(DeleteView):
return reverse_lazy('network.rule_list') return reverse_lazy('network.rule_list')
class SwitchPortList(SingleTableView):
model = SwitchPort
table_class = SwitchPortTable
template_name = "network/switch-port-list.html"
table_pagination = False
class SwitchPortDetail(UpdateView, SuccessMessageMixin):
model = SwitchPort
template_name = "network/switch-port-edit.html"
form_class = SwitchPortForm
success_message = _(u'Succesfully modified switch port!')
def get_success_url(self):
if 'pk' in self.kwargs:
return reverse_lazy('network.switch_port', kwargs=self.kwargs)
def get_context_data(self, **kwargs):
context = super(SwitchPortDetail, self).get_context_data(**kwargs)
context['switch_port_pk'] = self.object.pk
context['devices'] = EthernetDevice.objects.filter(
switch_port=self.object.pk)
return context
class SwitchPortCreate(CreateView, SuccessMessageMixin):
model = SwitchPort
template_name = "network/switch-port-create.html"
form_class = SwitchPortForm
success_message = _(u'Successfully created switch port!')
class SwitchPortDelete(DeleteView):
model = SwitchPort
template_name = "network/confirm/base_delete.html"
def get_success_url(self):
next = self.request.POST.get('next')
if next:
return next
else:
return reverse_lazy('network.switch_port_list')
class VlanList(SingleTableView): class VlanList(SingleTableView):
model = Vlan model = Vlan
table_class = VlanTable table_class = VlanTable
...@@ -690,3 +734,47 @@ def add_host_group(request, **kwargs): ...@@ -690,3 +734,47 @@ def add_host_group(request, **kwargs):
'group': group 'group': group
})) }))
return redirect(reverse_lazy('network.host', kwargs=kwargs)) return redirect(reverse_lazy('network.host', kwargs=kwargs))
def remove_switch_port_device(request, **kwargs):
device = EthernetDevice.objects.get(pk=kwargs['device_pk'])
# for get we show the confirmation page
if request.method == "GET":
return render(request, 'network/confirm/base_delete.html',
{'object': device})
# for post we actually remove the group from the host
elif request.method == "POST":
device.delete()
if not request.is_ajax():
messages.success(request, _(u"Successfully deleted ethernet device"
" %(name)s!" % {
'name': device.name,
}))
return redirect(reverse_lazy('network.switch_port',
kwargs={'pk': kwargs['pk']}))
def add_switch_port_device(request, **kwargs):
device_name = request.POST.get('device_name')
if (request.method == "POST" and device_name and len(device_name) > 0
and EthernetDevice.objects.filter(name=device_name).count() == 0):
switch_port = SwitchPort.objects.get(pk=kwargs['pk'])
new_device = EthernetDevice(name=device_name, switch_port=switch_port)
new_device.save()
if not request.is_ajax():
messages.success(request, _(u"Successfully added %(name)s to this"
" switch port" % {
'name': device_name,
}))
return redirect(reverse_lazy('network.switch_port', kwargs=kwargs))
elif not len(device_name) > 0:
messages.error(request, _("Ethernet device name cannot be empty!"))
return redirect(reverse_lazy('network.switch_port', kwargs=kwargs))
elif EthernetDevice.objects.get(name=device_name) is not None:
messages.error(request, _("There is already an ethernet device with"
" that name!"))
return redirect(reverse_lazy('network.switch_port', kwargs=kwargs))
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment