Commit 857316e0 by Kálmán Viktor

Merge branch 'issue-378' into 'master'

Firewall model to network GUI 

closes #378

See merge request !290
parents 9e28c78c ffa98f10
......@@ -33,6 +33,7 @@ from firewall.fields import (MACAddressField, val_alfanum, val_reverse_domain,
val_ipv6, val_mx,
IPNetworkField, IPAddressField)
from django.core.validators import MinValueValidator, MaxValueValidator
from django.core.urlresolvers import reverse
import django.conf
from django.db.models.signals import post_save, post_delete
from celery.exceptions import TimeoutError
......@@ -191,9 +192,8 @@ class Rule(models.Model):
return field.__class__.__name__.lower()
return None
@models.permalink
def get_absolute_url(self):
return ('network.rule', None, {'pk': self.pk})
return reverse('network.rule', kwargs={'pk': self.pk})
def get_chain_name(self, local, remote):
if local: # host or vlan
......@@ -476,9 +476,8 @@ class Vlan(AclBase, models.Model):
return "%s - %s" % ("managed" if self.managed else "unmanaged",
self.name)
@models.permalink
def get_absolute_url(self):
return ('network.vlan', None, {'vid': self.vid})
return reverse('network.vlan', kwargs={'vid': self.vid})
def get_random_addresses(self, used_v4, buffer_size=100, max_hosts=10000):
addresses = islice(self.network4.iter_hosts(), max_hosts)
......@@ -544,9 +543,8 @@ class VlanGroup(models.Model):
def __unicode__(self):
return self.name
@models.permalink
def get_absolute_url(self):
return ('network.vlan_group', None, {'pk': self.pk})
return reverse('network.vlan_group', kwargs={'pk': self.pk})
class Group(models.Model):
......@@ -567,9 +565,8 @@ class Group(models.Model):
def __unicode__(self):
return self.name
@models.permalink
def get_absolute_url(self):
return ('network.group', None, {'pk': self.pk})
return reverse('network.group', kwargs={'pk': self.pk})
class Host(models.Model):
......@@ -919,9 +916,8 @@ class Host(models.Model):
endpoints['ipv6'] = (self.ipv6, port) if public_port else None
return endpoints
@models.permalink
def get_absolute_url(self):
return ('network.host', None, {'pk': self.pk})
return reverse('network.host', kwargs={'pk': self.pk})
@property
def eui(self):
......@@ -970,6 +966,9 @@ class Firewall(models.Model):
logger.exception("get_dhcp_clients failed")
return {}
def get_absolute_url(self):
return reverse('network.firewall', kwargs={'pk': self.pk})
class Domain(models.Model):
name = models.CharField(max_length=40, validators=[val_domain],
......@@ -985,9 +984,8 @@ class Domain(models.Model):
def __unicode__(self):
return self.name
@models.permalink
def get_absolute_url(self):
return ('network.domain', None, {'pk': self.pk})
return reverse('network.domain', kwargs={'pk': self.pk})
class Record(models.Model):
......@@ -1056,9 +1054,8 @@ class Record(models.Model):
else:
return self.domain.name
@models.permalink
def get_absolute_url(self):
return ('network.record', None, {'pk': self.pk})
return reverse('network.record', kwargs={'pk': self.pk})
class Meta:
ordering = (
......@@ -1088,9 +1085,8 @@ class SwitchPort(models.Model):
self.untagged_vlan,
tagged_vlans)
@models.permalink
def get_absolute_url(self):
return ('network.switch_port', None, {'pk': self.pk})
return reverse('network.switch_port', kwargs={'pk': self.pk})
class EthernetDevice(models.Model):
......@@ -1143,9 +1139,8 @@ class BlacklistItem(models.Model):
verbose_name = _('blacklist item')
verbose_name_plural = _('blacklist')
@models.permalink
def get_absolute_url(self):
return ('network.blacklist', None, {'pk': self.pk})
return reverse('network.blacklist', kwargs={'pk': self.pk})
def send_task(sender, instance, created=False, **kwargs):
......
......@@ -23,8 +23,10 @@ from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Fieldset, Div, Submit, BaseInput
from crispy_forms.bootstrap import FormActions, FieldWithButtons, StrictButton
from firewall.models import (Host, Vlan, Domain, Group, Record, BlacklistItem,
Rule, VlanGroup, SwitchPort)
from firewall.models import (
Host, Vlan, Domain, Group, Record, BlacklistItem, Rule, VlanGroup,
SwitchPort, Firewall
)
class LinkButton(BaseInput):
......@@ -88,6 +90,21 @@ class DomainForm(ModelForm):
model = Domain
class FirewallForm(ModelForm):
helper = FormHelper()
helper.layout = Layout(
Div(Fieldset('', 'name', )),
FormActions(
Submit('submit', _("Save")),
LinkButton('back', _("Back"),
reverse_lazy('network.firewall_list'))
)
)
class Meta:
model = Firewall
class GroupForm(ModelForm):
helper = FormHelper()
helper.layout = Layout(
......
......@@ -12,6 +12,23 @@
width: 60px;
}
body {
padding-top: 40px;
}
/* note: this doesn't really work */
a i:hover {
text-decoration: none;
}
footer {
margin-top: 45px;
}
.messagelist {
margin-top: 25px;
}
#rule-list-table {
td {
text-align: center;
......
......@@ -245,3 +245,37 @@ class HostRecordsTable(Table):
fields = ("type", "fqdn")
order_by = ("name", )
empty_text = _("No records.")
class FirewallTable(Table):
pk = LinkColumn('network.firewall', args=[A('pk')],
verbose_name="ID")
class Meta:
model = SwitchPort
attrs = {'class': 'table table-striped'}
fields = ('pk', 'name', )
order_by = 'pk'
class FirewallRuleTable(Table):
color_desc = TemplateColumn(
template_name="network/columns/rule-short-description.html",
verbose_name=_("Short description"),
orderable=False,
)
actions = TemplateColumn(
template_name="network/columns/firewall-rule-actions.html",
verbose_name=_("Actions"),
orderable=False,
)
class Meta:
model = Rule
template = "django_tables2/table_no_page.html"
attrs = {'class': 'table table-striped table-hover table-condensed',
'id': "rule-list-table"}
fields = ('color_desc', 'extra', 'direction',
'action', 'proto', 'actions')
order_by = '-pk'
empty_text = _("No related rules found.")
......@@ -6,32 +6,6 @@
{% block title-site %}{% trans "Network" %} | CIRCLE{% endblock %}
{% block extra_link %}
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:200,400&amp;subset=latin,latin-ext' rel='stylesheet' type='text/css'>
<link href="{% static "network/network.css" %}" rel="stylesheet">
{% endblock %}
{% block extra_css %}
<style type="text/css">
body {
padding-top:40px;
}
/* note: this doesn't really work */
a i:hover {
text-decoration: none;
}
footer {
margin-top: 45px;
}
.messagelist {
margin-top: 25px;
}
</style>
{% endblock %}
{% block navbar-brand %}
<a class="navbar-brand" href="{% url "network.index" %}">CIRCLE Network</a>
{% endblock %}
......
{% load i18n %}
<div style="white-space: nowrap;">
<a href="{% url "network.rule_delete" pk=record.pk %}?next={{ request.path }}"><i class="fa fa-times"></i></a>
<a href="{% url "network.rule" pk=record.pk %}"><i class="fa fa-pencil"></i></a>
</div>
{% load i18n %}
{% load l10n %}
<div style="white-space: nowrap;">
<a href="{% url "network.rule_delete" pk=record.pk %}?from={{ request.path }}"><i class="fa fa-times"></i></a>
<a href="{% url "network.rule_delete" pk=record.pk %}?next={{ request.path }}"><i class="fa fa-times"></i></a>
<a href="{% url "network.rule" pk=record.pk %}"><i class="fa fa-pencil"></i></a>
</div>
......@@ -31,7 +31,7 @@
</div>
{% endif %}
<form action="" method="post">{% csrf_token %}
<input type="hidden" value="{{ request.GET.from }}" name="next" />
<input type="hidden" value="{{ request.GET.next }}" name="next" />
{% if confirmation %}
<label><p>
{% trans "If you are really sure, type in the object's name!" %}
......
{% extends "network/base.html" %}
{% load i18n %}
{% load staticfiles %}
{% load crispy_forms_tags %}
{% block title-page %}{% trans "Create" %} | {% trans "firewall" %}{% endblock %}
{% block content %}
<div class="page-header">
<h2>{% trans "Create a new firewall" %}</h2>
</div>
<div class="row">
<div class="col-sm-8">
{% crispy form %}
</div>
</div>
{% endblock %}
{% extends "network/base.html" %}
{% load render_table from django_tables2 %}
{% load i18n %}
{% load staticfiles %}
{% load crispy_forms_tags %}
{% block title-page %}{{ object.name }} | {% trans "firewall" %}{% endblock %}
{% block content %}
<div class="page-header">
<a href="{% url "network.firewall_delete" pk=object.pk %}" class="btn btn-danger pull-right">
<i class="fa fa-times-circle"></i> {% trans "Delete this firewall" %}
</a>
<h2>{{ object.name }}</h2>
</div>
<div class="row">
<div class="col-sm-5">
{% crispy form %}
</div>
</div>
<div class="page-header">
<h2>{% trans "Related rules" %}</h2>
</div>
<div class="row">
<div class="col-sm-12">
{% render_table rule_table %}
</div>
</div>
{% endblock %}
{% extends "network/base.html" %}
{% load render_table from django_tables2 %}
{% load i18n %}
{% load l10n %}
{% load staticfiles %}
{% block title-page %}{% trans "Firewalls" %}{% endblock %}
{% block content %}
<div class="page-header">
<a href="{% url "network.firewall_create" %}" class="btn btn-success pull-right">
<i class="fa fa-plus-circle"></i> {% trans "Create a new firewall" %}
</a>
<h1>{% trans "Firewalls" %}</h1>
</div>
<div class="table-responsive">
{% render_table table %}
</div>
{% endblock %}
......@@ -35,7 +35,7 @@
{% for group in group_rule_list %}
<div>
<h4 id="{{ group.pk }}_group_pk">{{ group.name }}
<a href="{% url "network.remove_host_group" pk=host_pk group_pk=group.pk %}?from={{ request.path }}">
<a href="{% url "network.remove_host_group" pk=host_pk group_pk=group.pk %}?next={{ request.path }}">
<i class="fa fa-times" style="vertical-align: middle;"></i></a>
<a href="{% url "network.group" group.pk %}">
<i class="fa fa-pencil" style="vertical-align: middle;"></i></a>
......
......@@ -22,25 +22,19 @@
{% url "network.switch_port_list" as u %}
{% trans "Switch ports" as t %}
{% include "network/menu-item.html" with href=u text=t %}
{% url "network.firewall_list" as u %}
{% trans "Firewalls" as t %}
{% include "network/menu-item.html" with href=u text=t %}
<li class="dropdown{% if "groups" in request.path %} active{% endif %}">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Groups <b class="caret"></b></a>
<ul class="dropdown-menu">
{% url "network.vlan_group_list" as u %}
{% trans "Vlan groups" as t %}
{% include "network/menu-item.html" with href=u text=t %}
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Groups <b class="caret"></b></a>
<ul class="dropdown-menu">
{% url "network.vlan_group_list" as u %}
{% trans "Vlan groups" as t %}
{% include "network/menu-item.html" with href=u text=t %}
{% url "network.group_list" as u %}
{% trans "Host groups" as t %}
{% include "network/menu-item.html" with href=u text=t %}
</ul>
{% url "network.group_list" as u %}
{% trans "Host groups" as t %}
{% include "network/menu-item.html" with href=u text=t %}
</ul>
</li>
{# <li><a href="/vlans/">{% trans "Vlans" %}</a></li> #}
{# <li><a href="/vlangroups/">{% trans "Vlan groups" %}</a></li> #}
{# <li><a href="/hostgroups/">{% trans "Host groups" %}</a></li> #}
{# <li><a href="/hosts/">{% trans "Hosts" %}</a></li> #}
{# <li><a href="/firewalls/">{% trans "Firewalls" %}</a></li> #}
{# <li><a href="/domains/">{% trans "Domains" %}</a></li> #}
{# <li><a href="/records/">{% trans "DNS records" %}</a></li> #}
{# <li><a href="/blacklist/">{% trans "Blacklist" %}</a></li> #}
......@@ -16,26 +16,27 @@
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
from django.conf.urls import patterns, url
from .views import (IndexView,
HostList, HostDetail, HostCreate, HostDelete,
VlanList, VlanDetail, VlanDelete, VlanCreate,
DomainList, DomainDetail, DomainDelete, DomainCreate,
GroupList, GroupDetail, GroupDelete, GroupCreate,
RecordList, RecordDetail, RecordCreate, RecordDelete,
BlacklistList, BlacklistDetail, BlacklistDelete,
BlacklistCreate,
RuleList, RuleDetail, RuleDelete, RuleCreate,
SwitchPortList, SwitchPortDetail, SwitchPortCreate,
SwitchPortDelete,
VlanGroupList, VlanGroupDetail, VlanGroupDelete,
VlanGroupCreate,
remove_host_group, add_host_group,
remove_switch_port_device, add_switch_port_device,
VlanAclUpdateView)
from .views import (
IndexView,
HostList, HostDetail, HostCreate, HostDelete,
VlanList, VlanDetail, VlanDelete, VlanCreate,
DomainList, DomainDetail, DomainDelete, DomainCreate,
GroupList, GroupDetail, GroupDelete, GroupCreate,
RecordList, RecordDetail, RecordCreate, RecordDelete,
BlacklistList, BlacklistDetail, BlacklistDelete, BlacklistCreate,
RuleList, RuleDetail, RuleDelete, RuleCreate,
SwitchPortList, SwitchPortDetail, SwitchPortCreate, SwitchPortDelete,
VlanGroupList, VlanGroupDetail, VlanGroupDelete, VlanGroupCreate,
FirewallList, FirewallDetail, FirewallCreate, FirewallDelete,
remove_host_group, add_host_group,
remove_switch_port_device, add_switch_port_device,
VlanAclUpdateView
)
urlpatterns = patterns(
'',
url('^$', IndexView.as_view(), name='network.index'),
# blacklist
url('^blacklist/$', BlacklistList.as_view(),
name='network.blacklist_list'),
url('^blacklist/create$', BlacklistCreate.as_view(),
......@@ -44,6 +45,8 @@ urlpatterns = patterns(
name='network.blacklist'),
url('^blacklist/delete/(?P<pk>\d+)/$', BlacklistDelete.as_view(),
name="network.blacklist_delete"),
# domain
url('^domains/$', DomainList.as_view(), name='network.domain_list'),
url('^domains/create$', DomainCreate.as_view(),
name='network.domain_create'),
......@@ -51,17 +54,33 @@ urlpatterns = patterns(
name='network.domain'),
url('^domains/delete/(?P<pk>\d+)/$', DomainDelete.as_view(),
name="network.domain_delete"),
# firewall
url('^firewalls/$', FirewallList.as_view(),
name='network.firewall_list'),
url('^firewalls/create$', FirewallCreate.as_view(),
name='network.firewall_create'),
url('^firewalls/(?P<pk>\d+)/$', FirewallDetail.as_view(),
name='network.firewall'),
url('^firewalls/delete/(?P<pk>\d+)/$', FirewallDelete.as_view(),
name="network.firewall_delete"),
# group (host)
url('^groups/$', GroupList.as_view(), name='network.group_list'),
url('^groups/create$', GroupCreate.as_view(),
name='network.group_create'),
url('^groups/(?P<pk>\d+)/$', GroupDetail.as_view(), name='network.group'),
url('^groups/delete/(?P<pk>\d+)/$', GroupDelete.as_view(),
name="network.group_delete"),
# host
url('^hosts/$', HostList.as_view(), name='network.host_list'),
url('^hosts/create$', HostCreate.as_view(), name='network.host_create'),
url('^hosts/(?P<pk>\d+)/$', HostDetail.as_view(), name='network.host'),
url('^hosts/delete/(?P<pk>\d+)/$', HostDelete.as_view(),
name="network.host_delete"),
# record
url('^records/$', RecordList.as_view(), name='network.record_list'),
url('^records/create$', RecordCreate.as_view(),
name='network.record_create'),
......@@ -69,10 +88,14 @@ urlpatterns = patterns(
name='network.record'),
url('^records/delete/(?P<pk>\d+)/$', RecordDelete.as_view(),
name="network.record_delete"),
# rule
url('^rules/$', RuleList.as_view(), name='network.rule_list'),
url('^rules/create$', RuleCreate.as_view(), name='network.rule_create'),
url('^rules/(?P<pk>\d+)/$', RuleDetail.as_view(),
name='network.rule'),
# switchport
url('^switchports/$', SwitchPortList.as_view(),
name='network.switch_port_list'),
url('^switchports/create$', SwitchPortCreate.as_view(),
......@@ -81,6 +104,8 @@ urlpatterns = patterns(
name='network.switch_port'),
url('^switchports/delete/(?P<pk>\d+)/$', SwitchPortDelete.as_view(),
name="network.switch_port_delete"),
# vlan
url('^vlans/$', VlanList.as_view(), name='network.vlan_list'),
url('^vlans/create$', VlanCreate.as_view(), name='network.vlan_create'),
url('^vlans/(?P<vid>\d+)/$', VlanDetail.as_view(), name='network.vlan'),
......@@ -88,6 +113,8 @@ urlpatterns = patterns(
name='network.vlan-acl'),
url('^vlans/delete/(?P<vid>\d+)/$', VlanDelete.as_view(),
name="network.vlan_delete"),
# vlangroup
url('^vlangroups/$', VlanGroupList.as_view(),
name='network.vlan_group_list'),
url('^vlangroups/create$', VlanGroupCreate.as_view(),
......
......@@ -28,15 +28,20 @@ from django.db.models import Q
from django_tables2 import SingleTableView
from firewall.models import (Host, Vlan, Domain, Group, Record, BlacklistItem,
Rule, VlanGroup, SwitchPort, EthernetDevice)
from firewall.models import (
Host, Vlan, Domain, Group, Record, BlacklistItem, Rule, VlanGroup,
SwitchPort, EthernetDevice, Firewall)
from vm.models import Interface
from .tables import (HostTable, VlanTable, SmallHostTable, DomainTable,
GroupTable, RecordTable, BlacklistItemTable, RuleTable,
VlanGroupTable, SmallRuleTable, SmallGroupRuleTable,
SmallRecordTable, SwitchPortTable, SmallDhcpTable, )
from .forms import (HostForm, VlanForm, DomainForm, GroupForm, RecordForm,
BlacklistItemForm, RuleForm, VlanGroupForm, SwitchPortForm)
from .tables import (
HostTable, VlanTable, SmallHostTable, DomainTable, GroupTable,
RecordTable, BlacklistItemTable, RuleTable, VlanGroupTable,
SmallRuleTable, SmallGroupRuleTable, SmallRecordTable, SwitchPortTable,
SmallDhcpTable, FirewallTable, FirewallRuleTable,
)
from .forms import (
HostForm, VlanForm, DomainForm, GroupForm, RecordForm, BlacklistItemForm,
RuleForm, VlanGroupForm, SwitchPortForm, FirewallForm
)
from django.contrib import messages
from django.contrib.messages.views import SuccessMessageMixin
......@@ -287,6 +292,53 @@ class DomainDelete(LoginRequiredMixin, SuperuserRequiredMixin, DeleteView):
return context
class FirewallList(LoginRequiredMixin, SuperuserRequiredMixin,
SingleTableView):
model = Firewall
table_class = FirewallTable
template_name = "network/firewall-list.html"
table_pagination = False
class FirewallDetail(LoginRequiredMixin, SuperuserRequiredMixin,
SuccessMessageMixin, UpdateView):
model = Firewall
template_name = "network/firewall-edit.html"
form_class = FirewallForm
success_message = _(u'Succesfully modified firewall.')
def get_success_url(self):
if 'pk' in self.kwargs:
return reverse_lazy('network.firewall', kwargs=self.kwargs)
def get_context_data(self, **kwargs):
context = super(FirewallDetail, self).get_context_data(**kwargs)
rules = Rule.objects.filter(firewall=self.object)
context['rule_table'] = FirewallRuleTable(rules,
request=self.request)
return context
class FirewallCreate(LoginRequiredMixin, SuperuserRequiredMixin,
SuccessMessageMixin, CreateView):
model = Firewall
template_name = "network/firewall-create.html"
form_class = FirewallForm
success_message = _(u'Successfully created firewall.')
class FirewallDelete(LoginRequiredMixin, SuperuserRequiredMixin, DeleteView):
model = Firewall
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.firewall_list')
class GroupList(LoginRequiredMixin, SuperuserRequiredMixin, SingleTableView):
model = Group
table_class = GroupTable
......
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