Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
Gelencsér Szabolcs
/
circlestack
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
c2e1edf1
authored
Sep 05, 2013
by
Bach Dániel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
firewall: add IPNetworkField
parent
5c30cc6f
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
137 additions
and
43 deletions
+137
-43
circle/dashboard/urls.py
+1
-2
circle/firewall/admin.py
+2
-1
circle/firewall/fields.py
+73
-0
circle/firewall/fw.py
+1
-1
circle/firewall/migrations/0033_auto__del_field_vlan_net4__del_field_vlan_prefix6__del_field_vlan_pref.py
+0
-0
circle/firewall/models.py
+59
-39
requirements/base.txt
+1
-0
No files found.
circle/dashboard/urls.py
View file @
c2e1edf1
...
...
@@ -5,5 +5,4 @@ from .views import IndexView, VmDetailView
urlpatterns
=
patterns
(
''
,
url
(
r'^$'
,
IndexView
.
as_view
()),
url
(
r'^vm/(?P<id>\d+)/$'
,
VmDetailView
.
as_view
(),
name
=
'dashboard.views.detail'
),
)
name
=
'dashboard.views.detail'
),)
circle/firewall/admin.py
View file @
c2e1edf1
...
...
@@ -38,8 +38,9 @@ class HostInline(contrib.admin.TabularInline):
class
VlanAdmin
(
admin
.
ModelAdmin
):
list_display
=
(
'vid'
,
'name'
,
'
ipv4'
,
'net_ipv4'
,
'ipv6'
,
'net_ipv
6'
,
list_display
=
(
'vid'
,
'name'
,
'
network4'
,
'network
6'
,
'description'
,
'domain'
,
'snat_ip'
,
)
search_fields
=
(
'vid'
,
'name'
,
'network4'
,
)
ordering
=
(
'vid'
,
)
inlines
=
(
RuleInline
,
)
...
...
circle/firewall/fields.py
View file @
c2e1edf1
...
...
@@ -4,6 +4,8 @@ from django.db import models
from
django.utils.translation
import
ugettext_lazy
as
_
from
django.utils.ipv6
import
is_valid_ipv6_address
from
south.modelsinspector
import
add_introspection_rules
from
django
import
forms
from
netaddr
import
IPNetwork
,
AddrFormatError
import
re
...
...
@@ -40,6 +42,77 @@ class MACAddressField(models.Field):
add_introspection_rules
([],
[
"firewall
\
.fields
\
.MACAddressField"
])
class
IPNetworkFormField
(
forms
.
Field
):
default_error_messages
=
{
'invalid'
:
_
(
u'Enter a valid IP network.
%
s'
),
}
def
validate
(
self
,
value
):
try
:
return
IPNetworkField
.
from_str
(
value
,
version
=
self
.
version
)
except
(
AddrFormatError
,
TypeError
),
e
:
raise
ValidationError
(
self
.
default_error_messages
[
'invalid'
]
%
unicode
(
e
))
def
__init__
(
self
,
*
args
,
**
kwargs
):
self
.
version
=
kwargs
[
'version'
]
del
kwargs
[
'version'
]
super
(
IPNetworkFormField
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
class
IPNetworkField
(
models
.
Field
):
description
=
_
(
'IP Network object'
)
__metaclass__
=
models
.
SubfieldBase
def
__init__
(
self
,
version
=
4
,
*
args
,
**
kwargs
):
kwargs
[
'max_length'
]
=
100
self
.
version
=
version
super
(
IPNetworkField
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
@staticmethod
def
from_str
(
value
,
version
):
if
not
value
or
value
==
""
:
return
None
if
isinstance
(
value
,
IPNetwork
):
return
value
return
IPNetwork
(
value
,
version
=
version
)
def
get_internal_type
(
self
):
return
"CharField"
def
to_python
(
self
,
value
):
return
IPNetworkField
.
from_str
(
value
,
self
.
version
)
def
get_db_prep_value
(
self
,
value
,
connection
,
prepared
=
False
):
if
not
value
or
value
==
""
:
return
None
if
isinstance
(
value
,
IPNetwork
):
if
self
.
version
==
4
:
return
'.'
.
join
(
map
(
lambda
x
:
"
%03
d"
%
x
,
value
.
ip
.
words
))
else
:
return
':'
.
join
(
map
(
lambda
x
:
"
%04
X"
%
x
,
value
.
ip
.
words
))
return
value
def
value_to_string
(
self
,
obj
):
value
=
self
.
_get_val_from_obj
(
obj
)
return
self
.
get_prep_value
(
value
)
def
clean
(
self
,
value
,
model_instance
):
value
=
super
(
IPNetworkField
,
self
)
.
clean
(
value
,
model_instance
)
return
self
.
get_prep_value
(
value
)
def
formfield
(
self
,
**
kwargs
):
defaults
=
{
'form_class'
:
IPNetworkFormField
}
defaults
[
'version'
]
=
self
.
version
defaults
.
update
(
kwargs
)
return
super
(
IPNetworkField
,
self
)
.
formfield
(
**
defaults
)
add_introspection_rules
([],
[
"^firewall
\
.fields
\
.IPNetworkField"
])
def
val_alfanum
(
value
):
"""Validate whether the parameter is a valid alphanumeric value."""
if
not
alfanum_re
.
match
(
value
):
...
...
circle/firewall/fw.py
View file @
c2e1edf1
...
...
@@ -203,7 +203,7 @@ class Firewall:
for
d_vlan
in
s_vlan
.
snat_to
.
all
():
self
.
iptablesnat
(
'-A POSTROUTING -s
%
s -o
%
s -j SNAT '
'--to-source
%
s'
%
(
s
_vlan
.
net_ipv4
(
),
d_vlan
.
interface
,
(
s
tr
(
s_vlan
.
network4
),
d_vlan
.
interface
,
s_vlan
.
snat_ip
))
# hard-wired rules
...
...
circle/firewall/migrations/0033_auto__del_field_vlan_net4__del_field_vlan_prefix6__del_field_vlan_pref.py
0 → 100644
View file @
c2e1edf1
This diff is collapsed.
Click to expand it.
circle/firewall/models.py
View file @
c2e1edf1
...
...
@@ -6,7 +6,7 @@ from django.forms import ValidationError
from
django.utils.translation
import
ugettext_lazy
as
_
from
firewall.fields
import
(
MACAddressField
,
val_alfanum
,
val_reverse_domain
,
val_domain
,
val_ipv4
,
val_ipv6
,
val_mx
,
ipv4_2_ipv6
)
ipv4_2_ipv6
,
IPNetworkField
)
from
django.core.validators
import
MinValueValidator
,
MaxValueValidator
import
django.conf
from
django.db.models.signals
import
post_save
...
...
@@ -70,8 +70,9 @@ class Rule(models.Model):
help_text
=
_
(
"If network address translation "
"shoud be done."
))
nat_dport
=
models
.
IntegerField
(
blank
=
True
,
null
=
True
,
help_text
=
_
(
"Rewrite destination port number to."
),
help_text
=
_
(
"Rewrite destination port "
"number to this if NAT is "
"needed."
),
validators
=
[
MinValueValidator
(
1
),
MaxValueValidator
(
65535
)])
created_at
=
models
.
DateTimeField
(
...
...
@@ -169,39 +170,31 @@ class Vlan(models.Model):
verbose_name
=
_
(
'Name'
),
help_text
=
_
(
'The short name of the subnet.'
),
validators
=
[
val_alfanum
])
prefix4
=
models
.
IntegerField
(
default
=
16
,
verbose_name
=
_
(
'IPv4 prefix length'
),
help_text
=
_
(
'The prefix length of the IPv4 subnet.'
))
prefix6
=
models
.
IntegerField
(
default
=
80
,
verbose_name
=
_
(
'IPv6 prefix length'
),
help_text
=
_
(
'The prefix length of the IPv6 subnet.'
))
interface
=
models
.
CharField
(
max_length
=
20
,
unique
=
True
,
verbose_name
=
_
(
'interface'
),
help_text
=
_
(
'The name of network interface the '
'gateway should serve this network on. '
'For example vlan0004 or eth2.'
))
net4
=
models
.
GenericIPAddressField
(
protocol
=
'ipv4'
,
unique
=
True
,
verbose_name
=
_
(
'IPv4 network'
),
help_text
=
_
(
'The network address of '
'the IPv4 subnet.'
))
net6
=
models
.
GenericIPAddressField
(
protocol
=
'ipv6'
,
unique
=
True
,
verbose_name
=
_
(
'IPv6 network'
),
help_text
=
_
(
'The network address of '
'the IPv6 subnet.'
))
ipv4
=
models
.
GenericIPAddressField
(
protocol
=
'ipv4'
,
unique
=
True
,
verbose_name
=
_
(
'IPv4 address'
),
help_text
=
_
(
'The IPv4 address of the gateway. '
'Recommended value is the last '
'valid address of the subnet, '
'for example '
'10.4.255.254 for 10.4.0.0/16.'
))
ipv6
=
models
.
GenericIPAddressField
(
protocol
=
'ipv6'
,
unique
=
True
,
verbose_name
=
_
(
'IPv6 address'
),
help_text
=
_
(
'The IPv6 address of the '
'gateway.'
))
network4
=
IPNetworkField
(
unique
=
False
,
version
=
4
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'IPv4 address/prefix'
),
help_text
=
_
(
'The IPv4 address and the prefix length '
'of the gateway.'
'Recommended value is the last '
'valid address of the subnet, '
'for example '
'10.4.255.254/16 for 10.4.0.0/16.'
))
network6
=
IPNetworkField
(
unique
=
False
,
version
=
6
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'IPv6 address/prefix'
),
help_text
=
_
(
'The IPv6 address and the prefix length '
'of the gateway.'
))
snat_ip
=
models
.
GenericIPAddressField
(
protocol
=
'ipv4'
,
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'NAT IP address'
),
...
...
@@ -257,18 +250,37 @@ class Vlan(models.Model):
def
__unicode__
(
self
):
return
self
.
name
def
net_ipv6
(
self
):
"""String representation of selected IPv6 network."""
return
self
.
net6
+
"/"
+
unicode
(
self
.
prefix6
)
def
net_ipv4
(
self
):
"""String representation of selected IPv4 network."""
return
self
.
net4
+
"/"
+
unicode
(
self
.
prefix4
)
@models.permalink
def
get_absolute_url
(
self
):
return
(
'network.vlan'
,
None
,
{
'vid'
:
self
.
vid
})
@property
def
net4
(
self
):
return
self
.
network4
.
network
@property
def
ipv4
(
self
):
return
self
.
network4
.
ip
@property
def
prefix4
(
self
):
return
self
.
network4
.
prefixlen
@property
def
net6
(
self
):
return
self
.
network6
.
network
@property
def
ipv6
(
self
):
return
self
.
network6
.
ip
@property
def
prefix6
(
self
):
return
self
.
network6
.
prefixlen
def
__unicode__
(
self
):
return
self
.
name
class
VlanGroup
(
models
.
Model
):
"""
...
...
@@ -389,6 +401,14 @@ class Host(models.Model):
def
__unicode__
(
self
):
return
self
.
hostname
@property
def
incoming_rules
(
self
):
return
self
.
rules
.
filter
(
direction
=
'1'
)
@property
def
outgoing_rules
(
self
):
return
self
.
rules
.
filter
(
direction
=
'0'
)
def
save
(
self
,
*
args
,
**
kwargs
):
id
=
self
.
id
if
not
self
.
id
and
self
.
ipv6
==
"auto"
:
...
...
requirements/base.txt
View file @
c2e1edf1
...
...
@@ -10,3 +10,4 @@ logutils==0.3.3
netaddr==0.7.10
South==0.8.1
psycopg2==2.5.1
netaddr==0.7.10
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment