diff --git a/circle/circle/settings/base.py b/circle/circle/settings/base.py
index 43903fa..259f408 100644
--- a/circle/circle/settings/base.py
+++ b/circle/circle/settings/base.py
@@ -3,6 +3,7 @@
 
 from os import environ
 from os.path import abspath, basename, dirname, join, normpath
+from json import loads 
 from socket import SOCK_STREAM
 from sys import path
 
@@ -223,6 +224,9 @@ THIRD_PARTY_APPS = (
 
 # Apps specific for this project go here.
 LOCAL_APPS = (
+    'vm',
+    'storage',
+    'firewall',
 )
 
 # See: https://docs.djangoproject.com/en/dev/ref/settings/#installed-apps
@@ -281,3 +285,5 @@ LOGGING = {
 # See: https://docs.djangoproject.com/en/dev/ref/settings/#wsgi-application
 WSGI_APPLICATION = '%s.wsgi.application' % SITE_NAME
 ########## END WSGI CONFIGURATION
+
+FIREWALL_SETTINGS = loads(get_env_variable('DJANGO_FIREWALL_SETTINGS'))
diff --git a/circle/firewall/__init__.py b/circle/firewall/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/circle/firewall/__init__.py
diff --git a/circle/firewall/admin.py b/circle/firewall/admin.py
new file mode 100644
index 0000000..448f619
--- /dev/null
+++ b/circle/firewall/admin.py
@@ -0,0 +1,119 @@
+# -*- coding: utf8 -*-
+
+from django.contrib import admin
+from firewall.models import *
+from django import contrib
+
+
+class RuleInline(contrib.admin.TabularInline):
+    model = Rule
+
+class RecordInline(contrib.admin.TabularInline):
+    model = Record
+
+class HostAdmin(admin.ModelAdmin):
+    list_display = ('hostname', 'vlan', 'ipv4', 'ipv6', 'pub_ipv4', 'mac',
+        'shared_ip', 'owner', 'description', 'reverse', 'list_groups')
+    ordering = ('hostname', )
+    list_filter = ('owner', 'vlan', 'groups')
+    search_fields = ('hostname', 'description', 'ipv4', 'ipv6', 'mac')
+    filter_horizontal = ('groups', )
+    inlines = (RuleInline, RecordInline)
+
+    @staticmethod
+    def list_groups(instance):
+        """Returns instance's groups' names as a comma-separated list."""
+        names = [group.name for group in instance.groups.all()]
+        return u', '.join(names)
+
+class HostInline(contrib.admin.TabularInline):
+    model = Host
+    fields = ('hostname', 'ipv4', 'ipv6', 'pub_ipv4', 'mac', 'shared_ip',
+        'owner', 'reverse')
+
+class VlanAdmin(admin.ModelAdmin):
+    list_display = ('vid', 'name', 'ipv4', 'net_ipv4', 'ipv6', 'net_ipv6',
+        'description', 'domain', 'snat_ip', )
+    ordering = ('vid', )
+    inlines = (RuleInline, )
+
+class RuleAdmin(admin.ModelAdmin):
+    list_display = ('r_type', 'color_desc', 'owner', 'extra', 'direction',
+        'accept', 'proto', 'sport', 'dport', 'nat', 'nat_dport', 'used_in')
+    list_filter = ('r_type', 'vlan', 'owner', 'direction', 'accept',
+        'proto', 'nat')
+
+    def color_desc(self, instance):
+        """Returns a colorful description of the instance."""
+        return (u'<span style="color: #FF0000;">[%(type)s]</span> '
+                u'%(src)s<span style="color: #0000FF;"> ▸ </span>%(dst)s '
+                u'%(para)s %(desc)s') % {
+                     'type': instance.r_type,
+                     'src': (instance.foreign_network.name
+                         if instance.direction == '1' else instance.r_type),
+                     'dst': (instance.r_type if instance.direction == '1'
+                         else instance.foreign_network.name),
+                     'para': (u'<span style="color: #00FF00;">' +
+                             (('proto=%s ' % instance.proto)
+                                 if instance.proto else '') +
+                             (('sport=%s ' % instance.sport)
+                                 if instance.sport else '') +
+                             (('dport=%s ' % instance.dport)
+                                 if instance.dport else '') +
+                               '</span>'),
+                     'desc': instance.description}
+    color_desc.allow_tags = True
+
+    @staticmethod
+    def vlan_l(instance):
+        """Returns instance's VLANs' names as a comma-separated list."""
+        names = [vlan.name for vlan in instance.foreign_network.vlans.all()]
+        return u', '.join(names)
+
+    @staticmethod
+    def used_in(instance):
+        for field in [instance.vlan, instance.vlangroup, instance.host,
+                instance.hostgroup, instance.firewall]:
+            if field:
+                return unicode(field) + ' ' + field._meta.object_name
+
+
+class AliasAdmin(admin.ModelAdmin):
+    list_display = ('alias', 'host')
+
+class GroupAdmin(admin.ModelAdmin):
+    list_display = ('name', 'owner', 'description')
+    inlines = (RuleInline, )
+
+class FirewallAdmin(admin.ModelAdmin):
+    inlines = (RuleInline, )
+
+class DomainAdmin(admin.ModelAdmin):
+    list_display = ('name', 'owner')
+
+class RecordAdmin(admin.ModelAdmin):
+    list_display = ('name_', 'type', 'address_', 'ttl', 'host', 'owner')
+
+    @staticmethod
+    def address_(instance):
+        a = instance.get_data()
+        return a['address'] if a else None
+
+    @staticmethod
+    def name_(instance):
+        a = instance.get_data()
+        return a['name'] if a else None
+
+class BlacklistAdmin(admin.ModelAdmin):
+    list_display = ('ipv4', 'reason', 'created_at', 'modified_at')
+
+admin.site.register(Host, HostAdmin)
+admin.site.register(Vlan, VlanAdmin)
+admin.site.register(Rule, RuleAdmin)
+admin.site.register(Group, GroupAdmin)
+admin.site.register(VlanGroup)
+admin.site.register(Firewall, FirewallAdmin)
+admin.site.register(Domain, DomainAdmin)
+admin.site.register(Record, RecordAdmin)
+admin.site.register(Blacklist, BlacklistAdmin)
+
diff --git a/circle/firewall/fields.py b/circle/firewall/fields.py
new file mode 100644
index 0000000..e2348dc
--- /dev/null
+++ b/circle/firewall/fields.py
@@ -0,0 +1,81 @@
+from django.core.exceptions import ValidationError
+from django.forms import fields
+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
+import re
+
+mac_re = re.compile(r'^([0-9a-fA-F]{2}([:-]?|$)){6}$')
+alfanum_re = re.compile(r'^[A-Za-z0-9_-]+$')
+domain_re = re.compile(r'^([A-Za-z0-9_-]\.?)+$')
+ipv4_re = re.compile('^[0-9]+\.([0-9]+)\.([0-9]+)\.([0-9]+)$')
+reverse_domain_re = re.compile(r'^(%\([abcd]\)d|[a-z0-9.-])+$')
+
+class MACAddressFormField(fields.RegexField):
+    default_error_messages = {
+        'invalid': _(u'Enter a valid MAC address.'),
+    }
+
+    def __init__(self, *args, **kwargs):
+        super(MACAddressFormField, self).__init__(mac_re, *args, **kwargs)
+
+class MACAddressField(models.Field):
+    empty_strings_allowed = False
+    def __init__(self, *args, **kwargs):
+        kwargs['max_length'] = 17
+        super(MACAddressField, self).__init__(*args, **kwargs)
+
+    def get_internal_type(self):
+        return 'CharField'
+
+    def formfield(self, **kwargs):
+        defaults = {'form_class': MACAddressFormField}
+        defaults.update(kwargs)
+        return super(MACAddressField, self).formfield(**defaults)
+add_introspection_rules([], ["firewall\.fields\.MACAddressField"])
+
+def val_alfanum(value):
+    """Validate whether the parameter is a valid alphanumeric value."""
+    if not alfanum_re.match(value):
+        raise ValidationError(_(u'%s - only letters, numbers, underscores '
+            'and hyphens are allowed!') % value)
+
+def is_valid_domain(value):
+    """Check whether the parameter is a valid domain name."""
+    return domain_re.match(value) is not None
+
+def val_domain(value):
+    """Validate whether the parameter is a valid domin name."""
+    if not is_valid_domain(value):
+        raise ValidationError(_(u'%s - invalid domain name') % value)
+
+def is_valid_reverse_domain(value):
+    """Check whether the parameter is a valid reverse domain name."""
+    return reverse_domain_re.match(value) is not None
+
+def val_reverse_domain(value):
+    """Validate whether the parameter is a valid reverse domain name."""
+    if not is_valid_reverse_domain(value):
+        raise ValidationError(u'%s - invalid reverse domain name' % value)
+
+def is_valid_ipv4_address(value):
+    """Check whether the parameter is a valid IPv4 address."""
+    return ipv4_re.match(value) is not None
+
+def val_ipv4(value):
+    """Validate whether the parameter is a valid IPv4 address."""
+    if not is_valid_ipv4_address(value):
+        raise ValidationError(_(u'%s - not an IPv4 address') % value)
+
+def val_ipv6(value):
+    """Validate whether the parameter is a valid IPv6 address."""
+    if not is_valid_ipv6_address(value):
+        raise ValidationError(_(u'%s - not an IPv6 address') % value)
+
+def ipv4_2_ipv6(ipv4):
+    """Convert IPv4 address string to IPv6 address string."""
+    val_ipv4(ipv4)
+    m = ipv4_re.match(ipv4)
+    return ("2001:738:2001:4031:%s:%s:%s:0" %
+        (m.group(1), m.group(2), m.group(3)))
diff --git a/circle/firewall/fw.py b/circle/firewall/fw.py
new file mode 100644
index 0000000..c4b2814
--- /dev/null
+++ b/circle/firewall/fw.py
@@ -0,0 +1,495 @@
+from django.contrib import auth
+from firewall import models
+import os
+import django.conf
+
+
+import subprocess
+import re
+import json
+from datetime import datetime, timedelta
+from django.db.models import Q
+
+
+settings = django.conf.settings.FIREWALL_SETTINGS
+class Firewall:
+    IPV6=False
+    RULES = None
+    RULES_NAT = []
+    vlans = None
+    dmz = None
+    pub = None
+    hosts = None
+    fw = None
+
+    def dportsport(self, rule, repl=True):
+        retval = ' '
+        if rule.proto == 'tcp' or rule.proto == 'udp':
+            retval = '-p %s ' % rule.proto
+            if rule.sport:
+                retval += ' --sport %s ' % rule.sport
+            if rule.dport:
+                retval += ' --dport %s ' % (rule.nat_dport
+                        if (repl and rule.nat and rule.direction == '1')
+                        else rule.dport)
+        elif rule.proto == 'icmp':
+            retval = '-p %s ' % rule.proto
+        return retval
+
+
+    def iptables(self, s):
+        """Append rule to filter table."""
+        self.RULES.append(s)
+
+    def iptablesnat(self, s):
+        """Append rule to NAT table."""
+        self.RULES_NAT.append(s)
+
+    def host2vlan(self, host, rule):
+        if not rule.foreign_network:
+            return
+
+        if self.IPV6 and host.ipv6:
+            ipaddr = host.ipv6 + '/112'
+        else:
+            ipaddr = host.ipv4
+
+        dport_sport = self.dportsport(rule)
+
+        for vlan in rule.foreign_network.vlans.all():
+            if rule.accept:
+                if rule.direction == '0' and vlan.name == 'PUB':
+                    if rule.dport == 25:
+                        self.iptables('-A PUB_OUT -s %s %s -p tcp '
+                                '--dport 25 -j LOG_ACC' %
+                                (ipaddr, rule.extra))
+                        break
+                    action = 'PUB_OUT'
+                else:
+                    action = 'LOG_ACC'
+            else:
+                action = 'LOG_DROP'
+
+            if rule.direction == '1': # going TO host
+                self.iptables('-A %s_%s -d %s %s %s -g %s' % (vlan,
+                    host.vlan, ipaddr, dport_sport, rule.extra, action))
+            else:
+                self.iptables('-A %s_%s -s %s %s %s -g %s' % (host.vlan,
+                    vlan, ipaddr, dport_sport, rule.extra, action))
+
+
+    def fw2vlan(self, rule):
+        if not rule.foreign_network:
+            return
+
+        dport_sport = self.dportsport(rule)
+
+        for vlan in rule.foreign_network.vlans.all():
+            if rule.direction == '1': # going TO host
+                self.iptables('-A INPUT -i %s %s %s -g %s' %
+                    (vlan.interface, dport_sport, rule.extra,
+                        'LOG_ACC' if rule.accept else 'LOG_DROP'))
+            else:
+                self.iptables('-A OUTPUT -o %s %s %s -g %s' %
+                    (vlan.interface, dport_sport, rule.extra,
+                        'LOG_ACC' if rule.accept else 'LOG_DROP'))
+
+    def vlan2vlan(self, l_vlan, rule):
+        if not rule.foreign_network:
+            return
+
+        dport_sport = self.dportsport(rule)
+
+        for vlan in rule.foreign_network.vlans.all():
+            if rule.accept:
+                if rule.direction == '0' and vlan.name == 'PUB':
+                    action = 'PUB_OUT'
+                else:
+                    action = 'LOG_ACC'
+            else:
+                action = 'LOG_DROP'
+
+            if rule.direction == '1': # going TO host
+                self.iptables('-A %s_%s %s %s -g %s' % (vlan, l_vlan,
+                    dport_sport, rule.extra, action))
+            else:
+                self.iptables('-A %s_%s %s %s -g %s' % (l_vlan, vlan,
+                    dport_sport, rule.extra, action))
+
+
+    def prerun(self):
+        self.iptables('*filter')
+        self.iptables(':INPUT DROP [88:6448]')
+        self.iptables(':FORWARD DROP [0:0]')
+        self.iptables(':OUTPUT DROP [50:6936]')
+
+        # initialize logging
+        self.iptables('-N LOG_DROP')
+        # windows port scan are silently dropped
+        self.iptables('-A LOG_DROP -p tcp --dport 445 -j DROP')
+        self.iptables('-A LOG_DROP -p udp --dport 137 -j DROP')
+        self.iptables('-A LOG_DROP -j LOG --log-level 7 '
+                '--log-prefix "[ipt][drop]"')
+        self.iptables('-A LOG_DROP -j DROP')
+        self.iptables('-N LOG_ACC')
+        self.iptables('-A LOG_ACC -j LOG --log-level 7 '
+                '--log-prefix "[ipt][isok]"')
+        self.iptables('-A LOG_ACC -j ACCEPT')
+
+        self.iptables('-N PUB_OUT')
+
+        self.iptables('-A FORWARD -m set --match-set blacklist src,dst -j DROP')
+        self.iptables('-A FORWARD -m state --state INVALID -g LOG_DROP')
+        self.iptables('-A FORWARD -m state --state ESTABLISHED,RELATED '
+                '-j ACCEPT')
+        self.iptables('-A FORWARD -p icmp --icmp-type echo-request '
+                '-g LOG_ACC')
+
+        self.iptables('-A INPUT -m set --match-set blacklist src -j DROP')
+        self.iptables('-A INPUT -m state --state INVALID -g LOG_DROP')
+        self.iptables('-A INPUT -i lo -j ACCEPT')
+        self.iptables('-A INPUT -m state --state ESTABLISHED,RELATED '
+                '-j ACCEPT')
+
+        self.iptables('-A OUTPUT -m state --state INVALID -g LOG_DROP')
+        self.iptables('-A OUTPUT -o lo -j ACCEPT')
+        self.iptables('-A OUTPUT -m state --state ESTABLISHED,RELATED '
+                '-j ACCEPT')
+
+
+    def postrun(self):
+        self.iptables('-A PUB_OUT -s 152.66.243.160/27 -p tcp --dport 25 '
+                '-j LOG_ACC')
+        self.iptables('-A PUB_OUT -s 152.66.243.160/27 -p tcp --dport 445 '
+                '-j LOG_ACC')
+        self.iptables('-A PUB_OUT -p tcp --dport 25 -j LOG_DROP')
+        self.iptables('-A PUB_OUT -p tcp --dport 445 -j LOG_DROP')
+        self.iptables('-A PUB_OUT -p udp --dport 445 -j LOG_DROP')
+
+        self.iptables('-A PUB_OUT -g LOG_ACC')
+        self.iptables('-A FORWARD -g LOG_DROP')
+        self.iptables('-A INPUT -g LOG_DROP')
+        self.iptables('-A OUTPUT -g LOG_DROP')
+        self.iptables('COMMIT')
+
+
+
+
+    def ipt_nat(self):
+        self.iptablesnat('*nat')
+        self.iptablesnat(':PREROUTING ACCEPT [0:0]')
+        self.iptablesnat(':INPUT ACCEPT [0:0]')
+        self.iptablesnat(':OUTPUT ACCEPT [1:708]')
+        self.iptablesnat(':POSTROUTING ACCEPT [1:708]')
+
+        # portforward
+        for host in self.hosts.exclude(pub_ipv4=None):
+            for rule in host.rules.filter(nat=True, direction='1'):
+                dport_sport = self.dportsport(rule, False)
+                if host.vlan.snat_ip:
+                    self.iptablesnat('-A PREROUTING -d %s %s %s -j DNAT '
+                            '--to-destination %s:%s' % (host.pub_ipv4,
+                                dport_sport, rule.extra, host.ipv4,
+                                rule.nat_dport))
+
+        # rules for machines with dedicated public IP
+        for host in self.hosts.exclude(shared_ip=True):
+            if host.pub_ipv4:
+                self.iptablesnat('-A PREROUTING -d %s -j DNAT '
+                        '--to-destination %s' % (host.pub_ipv4, host.ipv4))
+                self.iptablesnat('-A POSTROUTING -s %s -j SNAT '
+                        '--to-source %s' % (host.ipv4, host.pub_ipv4))
+
+        # default NAT rules for VLANs
+        for s_vlan in self.vlans:
+            if s_vlan.snat_ip:
+                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_vlan.snat_ip))
+
+
+        # hard-wired rules
+        self.iptablesnat('-A POSTROUTING -s 10.5.0.0/16 -o vlan0003 -j SNAT '
+                '--to-source 10.3.255.254') # man elerheto legyen
+        self.iptablesnat('-A POSTROUTING -s 10.5.0.0/16 -o vlan0008 -j SNAT '
+                '--to-source 10.0.0.247') # wolf network for printing
+        self.iptablesnat('-A POSTROUTING -s 10.3.0.0/16 -o vlan0002 -j SNAT '
+                '--to-source %s' % self.pub.ipv4) # kulonben nemmegy a du
+
+        self.iptablesnat('COMMIT')
+
+    def ipt_filter(self):
+        ipv4_re = re.compile('([0-9]{1,3}\.){3}[0-9]{1,3}')
+
+        # pre-run stuff
+        self.prerun()
+
+        # firewall's own rules
+        for f in self.fw:
+            for rule in f.rules.all():
+                self.fw2vlan(rule)
+
+        # zonak kozotti lancokra ugras
+        for s_vlan in self.vlans:
+            for d_vlan in self.vlans:
+                self.iptables('-N %s_%s' % (s_vlan, d_vlan))
+                self.iptables('-A FORWARD -i %s -o %s -g %s_%s' %
+                    (s_vlan.interface, d_vlan.interface, s_vlan, d_vlan))
+
+        # hosts' rules
+        for i_vlan in self.vlans:
+            for i_host in i_vlan.host_set.all():
+                for group in i_host.groups.all():
+                    for rule in group.rules.all():
+                        self.host2vlan(i_host, rule)
+                for rule in i_host.rules.all():
+                    self.host2vlan(i_host, rule)
+
+        # enable communication between VLANs
+        for s_vlan in self.vlans:
+            for rule in s_vlan.rules.all():
+                self.vlan2vlan(s_vlan, rule)
+
+        # zonak kozotti lancokat zarja le
+        for s_vlan in self.vlans:
+            for d_vlan in self.vlans:
+                self.iptables('-A %s_%s -g LOG_DROP' % (s_vlan, d_vlan))
+
+        # post-run stuff
+        self.postrun()
+
+        if self.IPV6:
+            self.RULES = [x for x in self.RULES if not ipv4_re.search(x)]
+            self.RULES = [x.replace('icmp', 'icmpv6') for x in self.RULES]
+
+    def __init__(self, IPV6=False):
+        self.RULES=[]
+        self.RULES_NAT=[]
+        self.IPV6 = IPV6
+        self.vlans = models.Vlan.objects.all()
+        self.hosts = models.Host.objects.all()
+        self.dmz = models.Vlan.objects.get(name='DMZ')
+        self.pub = models.Vlan.objects.get(name='PUB')
+        self.fw = models.Firewall.objects.all()
+        self.ipt_filter()
+        if not self.IPV6:
+            self.ipt_nat()
+
+    def reload(self):
+        if self.IPV6:
+            process = subprocess.Popen(['/usr/bin/ssh', 'fw2',
+                    '/usr/bin/sudo', '/sbin/ip6tables-restore', '-c'],
+                shell=False, stdin=subprocess.PIPE)
+            process.communicate('\n'.join(self.RULES) + '\n')
+        else:
+            process = subprocess.Popen(['/usr/bin/ssh', 'fw2',
+                    '/usr/bin/sudo', '/sbin/iptables-restore', '-c'],
+                shell=False, stdin=subprocess.PIPE)
+            process.communicate('\n'.join(self.RULES) + '\n' +
+                    '\n'.join(self.RULES_NAT) + '\n')
+
+    def get(self):
+        if self.IPV6:
+            return { 'filter': self.RULES, }
+        else:
+            return { 'filter': self.RULES, 'nat': self.RULES_NAT }
+
+    def show(self):
+        if self.IPV6:
+            return '\n'.join(self.RULES) + '\n'
+        else:
+            return ('\n'.join(self.RULES) + '\n' +
+                '\n'.join(self.RULES_NAT) + '\n')
+
+def ipset():
+    week = datetime.now()-timedelta(days=2)
+    return models.Blacklist.objects.filter(Q(type='tempban', modified_at__gte=week) | Q(type='permban')).values('ipv4', 'reason')
+
+
+def ipv6_to_octal(ipv6):
+    while len(ipv6.split(':')) < 8:
+        ipv6 = ipv6.replace('::', ':::')
+    octets = []
+    for part in ipv6.split(':'):
+        if not part:
+            octets.extend([0, 0])
+        else:
+            # Pad hex part to 4 digits.
+            part = '%04x' % int(part, 16)
+            octets.append(int(part[:2], 16))
+            octets.append(int(part[2:], 16))
+    return '\\' + '\\'.join(['%03o' % x for x in octets])
+
+def ipv4_to_arpa(ipv4, cname=False):
+    m2 = re.search(r'^([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)$', ipv4)
+    if cname:
+        return ('%s.dns1.%s.%s.%s.in-addr.arpa' %
+            (m2.group(4), m2.group(3), m2.group(2), m2.group(1)))
+    else:
+        return ('%s.%s.%s.%s.in-addr.arpa' %
+            (m2.group(4), m2.group(3), m2.group(2), m2.group(1)))
+
+def ipv6_to_arpa(ipv6):
+    while len(ipv6.split(':')) < 8:
+        ipv6 = ipv6.replace('::', ':::')
+    octets = []
+    for part in ipv6.split(':'):
+        if not part:
+            octets.extend([0, 0, 0, 0])
+        else:
+            # Pad hex part to 4 digits.
+            part = '%04x' % int(part, 16)
+            octets.insert(0, int(part[0], 16))
+            octets.insert(0, int(part[1], 16))
+            octets.insert(0, int(part[2], 16))
+            octets.insert(0, int(part[3], 16))
+    return '.'.join(['%1x' % x for x in octets]) + '.ip6.arpa'
+
+
+# =fqdn:ip:ttl          A, PTR
+# &fqdn:ip:x:ttl        NS
+# ZfqdnSOA
+# +fqdn:ip:ttl          A
+# ^                     PTR
+# C                     CNAME
+# :                     generic
+
+def dns():
+    vlans = models.Vlan.objects.all()
+    regex = re.compile(r'^([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)$')
+    DNS = []
+
+    for i_vlan in vlans:
+        m = regex.search(i_vlan.net4)
+        rev = i_vlan.reverse_domain
+
+        for i_host in i_vlan.host_set.all():
+            ipv4 = (i_host.pub_ipv4 if i_host.pub_ipv4 and
+                    not i_host.shared_ip else i_host.ipv4)
+            i = ipv4.split('.', 4)
+            reverse = (i_host.reverse if i_host.reverse and
+                    len(i_host.reverse) else i_host.get_fqdn())
+
+            # ipv4
+            if i_host.ipv4:
+                DNS.append("^%s:%s:%s" % (
+                    (rev % { 'a': int(i[0]), 'b': int(i[1]), 'c': int(i[2]),
+                             'd': int(i[3]) }),
+                    reverse, models.settings['dns_ttl']))
+
+            # ipv6
+            if i_host.ipv6:
+                DNS.append("^%s:%s:%s" % (ipv6_to_arpa(i_host.ipv6),
+                    reverse, models.settings['dns_ttl']))
+
+    for domain in models.Domain.objects.all():
+        DNS.append("Z%s:%s:support.ik.bme.hu::::::%s" % (domain.name,
+            settings['dns_hostname'], models.settings['dns_ttl']))
+
+    for r in models.Record.objects.all():
+        d = r.get_data()
+        if d['type'] == 'A':
+            DNS.append("+%s:%s:%s" % (d['name'], d['address'], d['ttl']))
+        elif d['type'] == 'AAAA':
+            DNS.append(":%s:28:%s:%s" % (d['name'],
+                ipv6_to_octal(d['address']), d['ttl']))
+        elif d['type'] == 'NS':
+            DNS.append("&%s::%s:%s" % (d['name'], d['address'], d['ttl']))
+        elif d['type'] == 'CNAME':
+            DNS.append("C%s:%s:%s" % (d['name'], d['address'], d['ttl']))
+        elif d['type'] == 'MX':
+            mx = d['address'].split(':', 2)
+            DNS.append("@%(fqdn)s::%(mx)s:%(dist)s:%(ttl)s" %
+                    {'fqdn': d['name'], 'mx': mx[1], 'dist': mx[0],
+                     'ttl': d['ttl']})
+        elif d['type'] == 'PTR':
+            DNS.append("^%s:%s:%s" % (d['name'], d['address'], d['ttl']))
+
+    return DNS
+    process = subprocess.Popen(['/usr/bin/ssh', 'tinydns@%s' %
+        settings['dns_hostname']], shell=False, stdin=subprocess.PIPE)
+    process.communicate("\n".join(DNS)+"\n")
+    # print "\n".join(DNS)+"\n"
+
+
+def prefix_to_mask(prefix):
+    t = [0, 0, 0, 0]
+    for i in range(0, 4):
+        if prefix > i * 8 + 7:
+            t[i] = 255
+        elif i * 8 < prefix and prefix <= (i + 1) * 8:
+            t[i] = 256 - (2 ** ((i + 1) * 8 - prefix))
+    return ".".join([str(i) for i in t])
+
+def dhcp():
+    vlans = models.Vlan.objects.all()
+    regex = re.compile(r'^([0-9]+)\.([0-9]+)\.[0-9]+\.[0-9]+\s+'
+            r'([0-9]+)\.([0-9]+)\.[0-9]+\.[0-9]+$')
+    DHCP = []
+
+# /tools/dhcp3/dhcpd.conf.generated
+
+    for i_vlan in vlans:
+        if(i_vlan.dhcp_pool):
+            m = regex.search(i_vlan.dhcp_pool)
+            if(m or i_vlan.dhcp_pool == "manual"):
+                DHCP.append ('''
+    # %(name)s - %(interface)s
+    subnet %(net)s netmask %(netmask)s {
+      %(extra)s;
+      option domain-name "%(domain)s";
+      option routers %(router)s;
+      option domain-name-servers %(dnsserver)s;
+      option ntp-servers %(ntp)s;
+      next-server %(tftp)s;
+      authoritative;
+      filename \"pxelinux.0\";
+      allow bootp; allow booting;
+    }'''        % {
+                    'net': i_vlan.net4,
+                    'netmask': prefix_to_mask(i_vlan.prefix4),
+                    'domain': i_vlan.domain,
+                    'router': i_vlan.ipv4,
+                    'ntp': i_vlan.ipv4,
+                    'dnsserver': settings['rdns_ip'],
+                    'extra': ("range %s" % i_vlan.dhcp_pool
+                        if m else "deny unknown-clients"),
+                    'interface': i_vlan.interface,
+                    'name': i_vlan.name,
+                    'tftp': i_vlan.ipv4
+                })
+
+                for i_host in i_vlan.host_set.all():
+                    DHCP.append ('''
+                    host %(hostname)s {
+                      hardware ethernet %(mac)s;
+                      fixed-address %(ipv4)s;
+                    }''' % {
+                        'hostname': i_host.hostname,
+                        'mac': i_host.mac,
+                        'ipv4': i_host.ipv4,
+                    })
+
+    return DHCP
+    process = subprocess.Popen(['/usr/bin/ssh', 'fw2',
+        'cat > /tools/dhcp3/dhcpd.conf.generated;'
+        'sudo /etc/init.d/isc-dhcp-server restart'], shell=False,
+        stdin=subprocess.PIPE)
+#   print "\n".join(DHCP)+"\n"
+    process.communicate("\n".join(DHCP)+"\n")
+
+
+'''
+i=2
+for mac, name, ipend in [("18:a9:05:64:19:aa", "mega6", 16), ("00:1e:0b:e9:79:1e", "blade1", 21), ("00:22:64:9c:fd:34", "blade2", 22), ("00:1e:0b:ec:65:46", "blade3", 23), ("b4:b5:2f:61:d2:5a", "cloud-man", 1)]:
+    h1 = models.Host(hostname= name, vlan=models.Vlan.objects.get(vid=3), mac=mac, ipv4="10.3.1.%d" % ipend, ipv6="2001:738:2001:4031:3:1:%d:0" % ipend, owner=auth.models.User.objects.get(username="bd"))
+    try:
+        h1.save()
+        h1.groups.add(models.Group.objects.get(name="netezhet manbol"))
+        h1.save()
+#       i = i + 1
+    except:
+        print "nemok %s" % name
+'''
+
diff --git a/circle/firewall/migrations/0001_initial.py b/circle/firewall/migrations/0001_initial.py
new file mode 100644
index 0000000..8a38f7f
--- /dev/null
+++ b/circle/firewall/migrations/0001_initial.py
@@ -0,0 +1,238 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        # Adding model 'Rule'
+        db.create_table('firewall_rule', (
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+            ('direction', self.gf('django.db.models.fields.BooleanField')(default=False)),
+            ('description', self.gf('django.db.models.fields.TextField')(blank=True)),
+            ('vlan', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['firewall.Vlan'])),
+            ('extra', self.gf('django.db.models.fields.TextField')(blank=True)),
+            ('action', self.gf('django.db.models.fields.BooleanField')(default=False)),
+        ))
+        db.send_create_signal('firewall', ['Rule'])
+
+        # Adding model 'Vlan'
+        db.create_table('firewall_vlan', (
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+            ('vid', self.gf('django.db.models.fields.IntegerField')(unique=True)),
+            ('name', self.gf('django.db.models.fields.CharField')(unique=True, max_length=20)),
+            ('prefix4', self.gf('django.db.models.fields.IntegerField')(default=16)),
+            ('prefix6', self.gf('django.db.models.fields.IntegerField')(default=80)),
+            ('interface', self.gf('django.db.models.fields.CharField')(unique=True, max_length=20)),
+            ('net4', self.gf('django.db.models.fields.GenericIPAddressField')(unique=True, max_length=39)),
+            ('net6', self.gf('django.db.models.fields.GenericIPAddressField')(unique=True, max_length=39)),
+            ('ipv4', self.gf('django.db.models.fields.GenericIPAddressField')(unique=True, max_length=39)),
+            ('ipv6', self.gf('django.db.models.fields.GenericIPAddressField')(unique=True, max_length=39)),
+            ('description', self.gf('django.db.models.fields.TextField')(blank=True)),
+            ('comment', self.gf('django.db.models.fields.TextField')(blank=True)),
+            ('domain', self.gf('django.db.models.fields.TextField')(blank=True)),
+            ('dhcp_pool', self.gf('django.db.models.fields.TextField')(blank=True)),
+        ))
+        db.send_create_signal('firewall', ['Vlan'])
+
+        # Adding M2M table for field en_dst on 'Vlan'
+        db.create_table('firewall_vlan_en_dst', (
+            ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
+            ('from_vlan', models.ForeignKey(orm['firewall.vlan'], null=False)),
+            ('to_vlan', models.ForeignKey(orm['firewall.vlan'], null=False))
+        ))
+        db.create_unique('firewall_vlan_en_dst', ['from_vlan_id', 'to_vlan_id'])
+
+        # Adding model 'Group'
+        db.create_table('firewall_group', (
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+            ('name', self.gf('django.db.models.fields.CharField')(unique=True, max_length=20)),
+        ))
+        db.send_create_signal('firewall', ['Group'])
+
+        # Adding M2M table for field rules on 'Group'
+        db.create_table('firewall_group_rules', (
+            ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
+            ('group', models.ForeignKey(orm['firewall.group'], null=False)),
+            ('rule', models.ForeignKey(orm['firewall.rule'], null=False))
+        ))
+        db.create_unique('firewall_group_rules', ['group_id', 'rule_id'])
+
+        # Adding model 'Host'
+        db.create_table('firewall_host', (
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+            ('hostname', self.gf('django.db.models.fields.CharField')(unique=True, max_length=20)),
+            ('mac', self.gf('firewall.models.MACAddressField')(unique=True, max_length=17)),
+            ('ipv4', self.gf('django.db.models.fields.GenericIPAddressField')(unique=True, max_length=39)),
+            ('pub_ipv4', self.gf('django.db.models.fields.GenericIPAddressField')(max_length=39, unique=True, null=True, blank=True)),
+            ('ipv6', self.gf('django.db.models.fields.GenericIPAddressField')(unique=True, max_length=39)),
+            ('description', self.gf('django.db.models.fields.TextField')(blank=True)),
+            ('comment', self.gf('django.db.models.fields.TextField')(blank=True)),
+            ('location', self.gf('django.db.models.fields.TextField')(blank=True)),
+            ('vlan', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['firewall.Vlan'])),
+            ('owner', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])),
+        ))
+        db.send_create_signal('firewall', ['Host'])
+
+        # Adding M2M table for field groups on 'Host'
+        db.create_table('firewall_host_groups', (
+            ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
+            ('host', models.ForeignKey(orm['firewall.host'], null=False)),
+            ('group', models.ForeignKey(orm['firewall.group'], null=False))
+        ))
+        db.create_unique('firewall_host_groups', ['host_id', 'group_id'])
+
+        # Adding M2M table for field rules on 'Host'
+        db.create_table('firewall_host_rules', (
+            ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
+            ('host', models.ForeignKey(orm['firewall.host'], null=False)),
+            ('rule', models.ForeignKey(orm['firewall.rule'], null=False))
+        ))
+        db.create_unique('firewall_host_rules', ['host_id', 'rule_id'])
+
+        # Adding model 'Firewall'
+        db.create_table('firewall_firewall', (
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+            ('name', self.gf('django.db.models.fields.CharField')(unique=True, max_length=20)),
+        ))
+        db.send_create_signal('firewall', ['Firewall'])
+
+        # Adding M2M table for field rules on 'Firewall'
+        db.create_table('firewall_firewall_rules', (
+            ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
+            ('firewall', models.ForeignKey(orm['firewall.firewall'], null=False)),
+            ('rule', models.ForeignKey(orm['firewall.rule'], null=False))
+        ))
+        db.create_unique('firewall_firewall_rules', ['firewall_id', 'rule_id'])
+
+
+    def backwards(self, orm):
+        # Deleting model 'Rule'
+        db.delete_table('firewall_rule')
+
+        # Deleting model 'Vlan'
+        db.delete_table('firewall_vlan')
+
+        # Removing M2M table for field en_dst on 'Vlan'
+        db.delete_table('firewall_vlan_en_dst')
+
+        # Deleting model 'Group'
+        db.delete_table('firewall_group')
+
+        # Removing M2M table for field rules on 'Group'
+        db.delete_table('firewall_group_rules')
+
+        # Deleting model 'Host'
+        db.delete_table('firewall_host')
+
+        # Removing M2M table for field groups on 'Host'
+        db.delete_table('firewall_host_groups')
+
+        # Removing M2M table for field rules on 'Host'
+        db.delete_table('firewall_host_rules')
+
+        # Deleting model 'Firewall'
+        db.delete_table('firewall_firewall')
+
+        # Removing M2M table for field rules on 'Firewall'
+        db.delete_table('firewall_firewall_rules')
+
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'firewall.firewall': {
+            'Meta': {'object_name': 'Firewall'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.host': {
+            'Meta': {'object_name': 'Host'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Group']", 'null': 'True', 'blank': 'True'}),
+            'hostname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'location': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'mac': ('firewall.models.MACAddressField', [], {'unique': 'True', 'max_length': '17'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'pub_ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'}),
+            'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Vlan']"})
+        },
+        'firewall.rule': {
+            'Meta': {'object_name': 'Rule'},
+            'action': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'direction': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'extra': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Vlan']"})
+        },
+        'firewall.vlan': {
+            'Meta': {'object_name': 'Vlan'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'dhcp_pool': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'domain': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'en_dst': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'interface': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'net4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'net6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'prefix4': ('django.db.models.fields.IntegerField', [], {'default': '16'}),
+            'prefix6': ('django.db.models.fields.IntegerField', [], {'default': '80'}),
+            'vid': ('django.db.models.fields.IntegerField', [], {'unique': 'True'})
+        }
+    }
+
+    complete_apps = ['firewall']
\ No newline at end of file
diff --git a/circle/firewall/migrations/0002_auto__add_field_rule_owner__chg_field_host_mac.py b/circle/firewall/migrations/0002_auto__add_field_rule_owner__chg_field_host_mac.py
new file mode 100644
index 0000000..2eeb23a
--- /dev/null
+++ b/circle/firewall/migrations/0002_auto__add_field_rule_owner__chg_field_host_mac.py
@@ -0,0 +1,123 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        # Adding field 'Rule.owner'
+        db.add_column('firewall_rule', 'owner',
+                      self.gf('django.db.models.fields.related.ForeignKey')(default=None, to=orm['auth.User']),
+                      keep_default=False)
+
+
+        # Changing field 'Host.mac'
+        db.alter_column('firewall_host', 'mac', self.gf('firewall.fields.MACAddressField')(unique=True, max_length=17))
+
+    def backwards(self, orm):
+        # Deleting field 'Rule.owner'
+        db.delete_column('firewall_rule', 'owner_id')
+
+
+        # Changing field 'Host.mac'
+        db.alter_column('firewall_host', 'mac', self.gf('firewall.models.MACAddressField')(max_length=17, unique=True))
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'firewall.firewall': {
+            'Meta': {'object_name': 'Firewall'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.host': {
+            'Meta': {'object_name': 'Host'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Group']", 'null': 'True', 'blank': 'True'}),
+            'hostname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'location': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'mac': ('firewall.fields.MACAddressField', [], {'unique': 'True', 'max_length': '17'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'pub_ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'}),
+            'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Vlan']"})
+        },
+        'firewall.rule': {
+            'Meta': {'object_name': 'Rule'},
+            'action': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'direction': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'extra': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Vlan']"})
+        },
+        'firewall.vlan': {
+            'Meta': {'object_name': 'Vlan'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'dhcp_pool': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'domain': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'en_dst': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'interface': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'net4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'net6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'prefix4': ('django.db.models.fields.IntegerField', [], {'default': '16'}),
+            'prefix6': ('django.db.models.fields.IntegerField', [], {'default': '80'}),
+            'vid': ('django.db.models.fields.IntegerField', [], {'unique': 'True'})
+        }
+    }
+
+    complete_apps = ['firewall']
\ No newline at end of file
diff --git a/circle/firewall/migrations/0003_auto__chg_field_rule_owner.py b/circle/firewall/migrations/0003_auto__chg_field_rule_owner.py
new file mode 100644
index 0000000..d1dcf2e
--- /dev/null
+++ b/circle/firewall/migrations/0003_auto__chg_field_rule_owner.py
@@ -0,0 +1,115 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+
+        # Changing field 'Rule.owner'
+        db.alter_column('firewall_rule', 'owner_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'], null=True))
+
+    def backwards(self, orm):
+
+        # User chose to not deal with backwards NULL issues for 'Rule.owner'
+        raise RuntimeError("Cannot reverse this migration. 'Rule.owner' and its values cannot be restored.")
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'firewall.firewall': {
+            'Meta': {'object_name': 'Firewall'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.host': {
+            'Meta': {'object_name': 'Host'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Group']", 'null': 'True', 'blank': 'True'}),
+            'hostname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'location': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'mac': ('firewall.fields.MACAddressField', [], {'unique': 'True', 'max_length': '17'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'pub_ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'}),
+            'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Vlan']"})
+        },
+        'firewall.rule': {
+            'Meta': {'object_name': 'Rule'},
+            'action': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'direction': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'extra': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Vlan']"})
+        },
+        'firewall.vlan': {
+            'Meta': {'object_name': 'Vlan'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'dhcp_pool': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'domain': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'en_dst': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'interface': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'net4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'net6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'prefix4': ('django.db.models.fields.IntegerField', [], {'default': '16'}),
+            'prefix6': ('django.db.models.fields.IntegerField', [], {'default': '80'}),
+            'vid': ('django.db.models.fields.IntegerField', [], {'unique': 'True'})
+        }
+    }
+
+    complete_apps = ['firewall']
\ No newline at end of file
diff --git a/circle/firewall/migrations/0004_auto__del_field_host_vlan.py b/circle/firewall/migrations/0004_auto__del_field_host_vlan.py
new file mode 100644
index 0000000..cc7a9fc
--- /dev/null
+++ b/circle/firewall/migrations/0004_auto__del_field_host_vlan.py
@@ -0,0 +1,126 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        # Deleting field 'Host.vlan'
+        db.delete_column('firewall_host', 'vlan_id')
+
+        # Adding M2M table for field vlan on 'Host'
+        db.create_table('firewall_host_vlan', (
+            ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
+            ('host', models.ForeignKey(orm['firewall.host'], null=False)),
+            ('vlan', models.ForeignKey(orm['firewall.vlan'], null=False))
+        ))
+        db.create_unique('firewall_host_vlan', ['host_id', 'vlan_id'])
+
+
+    def backwards(self, orm):
+
+        # User chose to not deal with backwards NULL issues for 'Host.vlan'
+        raise RuntimeError("Cannot reverse this migration. 'Host.vlan' and its values cannot be restored.")
+        # Removing M2M table for field vlan on 'Host'
+        db.delete_table('firewall_host_vlan')
+
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'firewall.firewall': {
+            'Meta': {'object_name': 'Firewall'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.host': {
+            'Meta': {'object_name': 'Host'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Group']", 'null': 'True', 'blank': 'True'}),
+            'hostname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39', 'blank': 'True'}),
+            'location': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'mac': ('firewall.fields.MACAddressField', [], {'unique': 'True', 'max_length': '17'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'pub_ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'}),
+            'vlan': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.rule': {
+            'Meta': {'object_name': 'Rule'},
+            'action': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'direction': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'extra': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Vlan']"})
+        },
+        'firewall.vlan': {
+            'Meta': {'object_name': 'Vlan'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'dhcp_pool': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'domain': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'en_dst': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'interface': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'net4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'net6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'prefix4': ('django.db.models.fields.IntegerField', [], {'default': '16'}),
+            'prefix6': ('django.db.models.fields.IntegerField', [], {'default': '80'}),
+            'vid': ('django.db.models.fields.IntegerField', [], {'unique': 'True'})
+        }
+    }
+
+    complete_apps = ['firewall']
\ No newline at end of file
diff --git a/circle/firewall/migrations/0005_auto__del_field_rule_vlan__add_field_host_vlan.py b/circle/firewall/migrations/0005_auto__del_field_rule_vlan__add_field_host_vlan.py
new file mode 100644
index 0000000..b38d6c7
--- /dev/null
+++ b/circle/firewall/migrations/0005_auto__del_field_rule_vlan__add_field_host_vlan.py
@@ -0,0 +1,145 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        # Deleting field 'Rule.vlan'
+        db.delete_column('firewall_rule', 'vlan_id')
+
+        # Adding M2M table for field vlan on 'Rule'
+        db.create_table('firewall_rule_vlan', (
+            ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
+            ('rule', models.ForeignKey(orm['firewall.rule'], null=False)),
+            ('vlan', models.ForeignKey(orm['firewall.vlan'], null=False))
+        ))
+        db.create_unique('firewall_rule_vlan', ['rule_id', 'vlan_id'])
+
+        # Adding field 'Host.vlan'
+        db.add_column('firewall_host', 'vlan',
+                      self.gf('django.db.models.fields.related.ForeignKey')(default=None, to=orm['firewall.Vlan']),
+                      keep_default=False)
+
+        # Removing M2M table for field vlan on 'Host'
+        db.delete_table('firewall_host_vlan')
+
+
+    def backwards(self, orm):
+
+        # User chose to not deal with backwards NULL issues for 'Rule.vlan'
+        raise RuntimeError("Cannot reverse this migration. 'Rule.vlan' and its values cannot be restored.")
+        # Removing M2M table for field vlan on 'Rule'
+        db.delete_table('firewall_rule_vlan')
+
+        # Deleting field 'Host.vlan'
+        db.delete_column('firewall_host', 'vlan_id')
+
+        # Adding M2M table for field vlan on 'Host'
+        db.create_table('firewall_host_vlan', (
+            ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
+            ('host', models.ForeignKey(orm['firewall.host'], null=False)),
+            ('vlan', models.ForeignKey(orm['firewall.vlan'], null=False))
+        ))
+        db.create_unique('firewall_host_vlan', ['host_id', 'vlan_id'])
+
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'firewall.firewall': {
+            'Meta': {'object_name': 'Firewall'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.host': {
+            'Meta': {'object_name': 'Host'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Group']", 'null': 'True', 'blank': 'True'}),
+            'hostname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39', 'blank': 'True'}),
+            'location': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'mac': ('firewall.fields.MACAddressField', [], {'unique': 'True', 'max_length': '17'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'pub_ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'}),
+            'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Vlan']"})
+        },
+        'firewall.rule': {
+            'Meta': {'object_name': 'Rule'},
+            'action': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'direction': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'extra': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'vlan': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.vlan': {
+            'Meta': {'object_name': 'Vlan'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'dhcp_pool': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'domain': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'en_dst': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'interface': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'net4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'net6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'prefix4': ('django.db.models.fields.IntegerField', [], {'default': '16'}),
+            'prefix6': ('django.db.models.fields.IntegerField', [], {'default': '80'}),
+            'vid': ('django.db.models.fields.IntegerField', [], {'unique': 'True'})
+        }
+    }
+
+    complete_apps = ['firewall']
\ No newline at end of file
diff --git a/circle/firewall/migrations/0006_auto__add_field_rule_r_type.py b/circle/firewall/migrations/0006_auto__add_field_rule_r_type.py
new file mode 100644
index 0000000..09ab256
--- /dev/null
+++ b/circle/firewall/migrations/0006_auto__add_field_rule_r_type.py
@@ -0,0 +1,118 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        # Adding field 'Rule.r_type'
+        db.add_column('firewall_rule', 'r_type',
+                      self.gf('django.db.models.fields.CharField')(default=None, max_length=10),
+                      keep_default=False)
+
+
+    def backwards(self, orm):
+        # Deleting field 'Rule.r_type'
+        db.delete_column('firewall_rule', 'r_type')
+
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'firewall.firewall': {
+            'Meta': {'object_name': 'Firewall'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.host': {
+            'Meta': {'object_name': 'Host'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Group']", 'null': 'True', 'blank': 'True'}),
+            'hostname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39', 'blank': 'True'}),
+            'location': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'mac': ('firewall.fields.MACAddressField', [], {'unique': 'True', 'max_length': '17'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'pub_ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'}),
+            'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Vlan']"})
+        },
+        'firewall.rule': {
+            'Meta': {'object_name': 'Rule'},
+            'action': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'direction': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'extra': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'r_type': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
+            'vlan': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.vlan': {
+            'Meta': {'object_name': 'Vlan'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'dhcp_pool': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'domain': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'en_dst': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'interface': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'net4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'net6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'prefix4': ('django.db.models.fields.IntegerField', [], {'default': '16'}),
+            'prefix6': ('django.db.models.fields.IntegerField', [], {'default': '80'}),
+            'vid': ('django.db.models.fields.IntegerField', [], {'unique': 'True'})
+        }
+    }
+
+    complete_apps = ['firewall']
\ No newline at end of file
diff --git a/circle/firewall/migrations/0007_auto.py b/circle/firewall/migrations/0007_auto.py
new file mode 100644
index 0000000..7d1dd80
--- /dev/null
+++ b/circle/firewall/migrations/0007_auto.py
@@ -0,0 +1,122 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        # Adding M2M table for field rules on 'Vlan'
+        db.create_table('firewall_vlan_rules', (
+            ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
+            ('vlan', models.ForeignKey(orm['firewall.vlan'], null=False)),
+            ('rule', models.ForeignKey(orm['firewall.rule'], null=False))
+        ))
+        db.create_unique('firewall_vlan_rules', ['vlan_id', 'rule_id'])
+
+
+    def backwards(self, orm):
+        # Removing M2M table for field rules on 'Vlan'
+        db.delete_table('firewall_vlan_rules')
+
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'firewall.firewall': {
+            'Meta': {'object_name': 'Firewall'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.host': {
+            'Meta': {'object_name': 'Host'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Group']", 'null': 'True', 'blank': 'True'}),
+            'hostname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39', 'blank': 'True'}),
+            'location': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'mac': ('firewall.fields.MACAddressField', [], {'unique': 'True', 'max_length': '17'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'pub_ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'}),
+            'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Vlan']"})
+        },
+        'firewall.rule': {
+            'Meta': {'object_name': 'Rule'},
+            'action': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'direction': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'extra': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'r_type': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
+            'vlan': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.vlan': {
+            'Meta': {'object_name': 'Vlan'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'dhcp_pool': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'domain': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'en_dst': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'interface': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'net4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'net6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'prefix4': ('django.db.models.fields.IntegerField', [], {'default': '16'}),
+            'prefix6': ('django.db.models.fields.IntegerField', [], {'default': '80'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'firewall_vlan_related'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['firewall.Rule']"}),
+            'vid': ('django.db.models.fields.IntegerField', [], {'unique': 'True'})
+        }
+    }
+
+    complete_apps = ['firewall']
\ No newline at end of file
diff --git a/circle/firewall/migrations/0008_auto__add_field_rule_nat__add_field_rule_nat_dport.py b/circle/firewall/migrations/0008_auto__add_field_rule_nat__add_field_rule_nat_dport.py
new file mode 100644
index 0000000..246c722
--- /dev/null
+++ b/circle/firewall/migrations/0008_auto__add_field_rule_nat__add_field_rule_nat_dport.py
@@ -0,0 +1,129 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        # Adding field 'Rule.nat'
+        db.add_column('firewall_rule', 'nat',
+                      self.gf('django.db.models.fields.BooleanField')(default=False),
+                      keep_default=False)
+
+        # Adding field 'Rule.nat_dport'
+        db.add_column('firewall_rule', 'nat_dport',
+                      self.gf('django.db.models.fields.IntegerField')(default=None),
+                      keep_default=False)
+
+
+    def backwards(self, orm):
+        # Deleting field 'Rule.nat'
+        db.delete_column('firewall_rule', 'nat')
+
+        # Deleting field 'Rule.nat_dport'
+        db.delete_column('firewall_rule', 'nat_dport')
+
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'firewall.firewall': {
+            'Meta': {'object_name': 'Firewall'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.host': {
+            'Meta': {'object_name': 'Host'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Group']", 'null': 'True', 'blank': 'True'}),
+            'hostname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39', 'blank': 'True'}),
+            'location': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'mac': ('firewall.fields.MACAddressField', [], {'unique': 'True', 'max_length': '17'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'pub_ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'}),
+            'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Vlan']"})
+        },
+        'firewall.rule': {
+            'Meta': {'object_name': 'Rule'},
+            'action': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'direction': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'extra': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nat': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'nat_dport': ('django.db.models.fields.IntegerField', [], {}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'r_type': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
+            'vlan': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.vlan': {
+            'Meta': {'object_name': 'Vlan'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'dhcp_pool': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'domain': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'en_dst': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'interface': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'net4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'net6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'prefix4': ('django.db.models.fields.IntegerField', [], {'default': '16'}),
+            'prefix6': ('django.db.models.fields.IntegerField', [], {'default': '80'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'firewall_vlan_related'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['firewall.Rule']"}),
+            'vid': ('django.db.models.fields.IntegerField', [], {'unique': 'True'})
+        }
+    }
+
+    complete_apps = ['firewall']
\ No newline at end of file
diff --git a/circle/firewall/migrations/0009_auto__add_field_vlan_snat_ip.py b/circle/firewall/migrations/0009_auto__add_field_vlan_snat_ip.py
new file mode 100644
index 0000000..3fce011
--- /dev/null
+++ b/circle/firewall/migrations/0009_auto__add_field_vlan_snat_ip.py
@@ -0,0 +1,144 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        # Adding field 'Vlan.snat_ip'
+        db.add_column('firewall_vlan', 'snat_ip',
+                      self.gf('django.db.models.fields.GenericIPAddressField')(default='152.66.243.160', max_length=39, blank=True),
+                      keep_default=False)
+
+        # Removing M2M table for field en_dst on 'Vlan'
+        db.delete_table('firewall_vlan_en_dst')
+
+        # Adding M2M table for field snat_to on 'Vlan'
+        db.create_table('firewall_vlan_snat_to', (
+            ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
+            ('from_vlan', models.ForeignKey(orm['firewall.vlan'], null=False)),
+            ('to_vlan', models.ForeignKey(orm['firewall.vlan'], null=False))
+        ))
+        db.create_unique('firewall_vlan_snat_to', ['from_vlan_id', 'to_vlan_id'])
+
+
+    def backwards(self, orm):
+        # Deleting field 'Vlan.snat_ip'
+        db.delete_column('firewall_vlan', 'snat_ip')
+
+        # Adding M2M table for field en_dst on 'Vlan'
+        db.create_table('firewall_vlan_en_dst', (
+            ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
+            ('from_vlan', models.ForeignKey(orm['firewall.vlan'], null=False)),
+            ('to_vlan', models.ForeignKey(orm['firewall.vlan'], null=False))
+        ))
+        db.create_unique('firewall_vlan_en_dst', ['from_vlan_id', 'to_vlan_id'])
+
+        # Removing M2M table for field snat_to on 'Vlan'
+        db.delete_table('firewall_vlan_snat_to')
+
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'firewall.firewall': {
+            'Meta': {'object_name': 'Firewall'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.host': {
+            'Meta': {'object_name': 'Host'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Group']", 'null': 'True', 'blank': 'True'}),
+            'hostname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39', 'blank': 'True'}),
+            'location': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'mac': ('firewall.fields.MACAddressField', [], {'unique': 'True', 'max_length': '17'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'pub_ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'}),
+            'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Vlan']"})
+        },
+        'firewall.rule': {
+            'Meta': {'object_name': 'Rule'},
+            'action': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'direction': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'extra': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nat': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'nat_dport': ('django.db.models.fields.IntegerField', [], {}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'r_type': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
+            'vlan': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.vlan': {
+            'Meta': {'object_name': 'Vlan'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'dhcp_pool': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'domain': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'interface': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'net4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'net6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'prefix4': ('django.db.models.fields.IntegerField', [], {'default': '16'}),
+            'prefix6': ('django.db.models.fields.IntegerField', [], {'default': '80'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'firewall_vlan_related'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['firewall.Rule']"}),
+            'snat_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'blank': 'True'}),
+            'snat_to': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'}),
+            'vid': ('django.db.models.fields.IntegerField', [], {'unique': 'True'})
+        }
+    }
+
+    complete_apps = ['firewall']
\ No newline at end of file
diff --git a/circle/firewall/migrations/0010_auto__chg_field_vlan_snat_ip.py b/circle/firewall/migrations/0010_auto__chg_field_vlan_snat_ip.py
new file mode 100644
index 0000000..8c213f4
--- /dev/null
+++ b/circle/firewall/migrations/0010_auto__chg_field_vlan_snat_ip.py
@@ -0,0 +1,120 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+
+        # Changing field 'Vlan.snat_ip'
+        db.alter_column('firewall_vlan', 'snat_ip', self.gf('django.db.models.fields.GenericIPAddressField')(max_length=39, null=True))
+
+    def backwards(self, orm):
+
+        # User chose to not deal with backwards NULL issues for 'Vlan.snat_ip'
+        raise RuntimeError("Cannot reverse this migration. 'Vlan.snat_ip' and its values cannot be restored.")
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'firewall.firewall': {
+            'Meta': {'object_name': 'Firewall'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.host': {
+            'Meta': {'object_name': 'Host'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Group']", 'null': 'True', 'blank': 'True'}),
+            'hostname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39', 'blank': 'True'}),
+            'location': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'mac': ('firewall.fields.MACAddressField', [], {'unique': 'True', 'max_length': '17'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'pub_ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'}),
+            'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Vlan']"})
+        },
+        'firewall.rule': {
+            'Meta': {'object_name': 'Rule'},
+            'action': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'direction': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'extra': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nat': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'nat_dport': ('django.db.models.fields.IntegerField', [], {}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'r_type': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
+            'vlan': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.vlan': {
+            'Meta': {'object_name': 'Vlan'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'dhcp_pool': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'domain': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'interface': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'net4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'net6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'prefix4': ('django.db.models.fields.IntegerField', [], {'default': '16'}),
+            'prefix6': ('django.db.models.fields.IntegerField', [], {'default': '80'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'firewall_vlan_related'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['firewall.Rule']"}),
+            'snat_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
+            'snat_to': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'}),
+            'vid': ('django.db.models.fields.IntegerField', [], {'unique': 'True'})
+        }
+    }
+
+    complete_apps = ['firewall']
\ No newline at end of file
diff --git a/circle/firewall/migrations/0011_auto__del_field_rule_action__add_field_rule_dport__add_field_rule_spor.py b/circle/firewall/migrations/0011_auto__del_field_rule_action__add_field_rule_dport__add_field_rule_spor.py
new file mode 100644
index 0000000..e3edcd1
--- /dev/null
+++ b/circle/firewall/migrations/0011_auto__del_field_rule_action__add_field_rule_dport__add_field_rule_spor.py
@@ -0,0 +1,157 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        # Deleting field 'Rule.action'
+        db.delete_column('firewall_rule', 'action')
+
+        # Adding field 'Rule.dport'
+        db.add_column('firewall_rule', 'dport',
+                      self.gf('django.db.models.fields.IntegerField')(null=True, blank=True),
+                      keep_default=False)
+
+        # Adding field 'Rule.sport'
+        db.add_column('firewall_rule', 'sport',
+                      self.gf('django.db.models.fields.IntegerField')(null=True, blank=True),
+                      keep_default=False)
+
+        # Adding field 'Rule.proto'
+        db.add_column('firewall_rule', 'proto',
+                      self.gf('django.db.models.fields.CharField')(max_length=10, null=True, blank=True),
+                      keep_default=False)
+
+        # Adding field 'Rule.accept'
+        db.add_column('firewall_rule', 'accept',
+                      self.gf('django.db.models.fields.BooleanField')(default=False),
+                      keep_default=False)
+
+
+    def backwards(self, orm):
+        # Adding field 'Rule.action'
+        db.add_column('firewall_rule', 'action',
+                      self.gf('django.db.models.fields.BooleanField')(default=False),
+                      keep_default=False)
+
+        # Deleting field 'Rule.dport'
+        db.delete_column('firewall_rule', 'dport')
+
+        # Deleting field 'Rule.sport'
+        db.delete_column('firewall_rule', 'sport')
+
+        # Deleting field 'Rule.proto'
+        db.delete_column('firewall_rule', 'proto')
+
+        # Deleting field 'Rule.accept'
+        db.delete_column('firewall_rule', 'accept')
+
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'firewall.firewall': {
+            'Meta': {'object_name': 'Firewall'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.host': {
+            'Meta': {'object_name': 'Host'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Group']", 'null': 'True', 'blank': 'True'}),
+            'hostname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39', 'blank': 'True'}),
+            'location': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'mac': ('firewall.fields.MACAddressField', [], {'unique': 'True', 'max_length': '17'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'pub_ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'}),
+            'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Vlan']"})
+        },
+        'firewall.rule': {
+            'Meta': {'object_name': 'Rule'},
+            'accept': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'direction': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'dport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'extra': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nat': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'nat_dport': ('django.db.models.fields.IntegerField', [], {}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'proto': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
+            'r_type': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
+            'sport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'vlan': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.vlan': {
+            'Meta': {'object_name': 'Vlan'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'dhcp_pool': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'domain': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'interface': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'net4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'net6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'prefix4': ('django.db.models.fields.IntegerField', [], {'default': '16'}),
+            'prefix6': ('django.db.models.fields.IntegerField', [], {'default': '80'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'firewall_vlan_related'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['firewall.Rule']"}),
+            'snat_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
+            'snat_to': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'}),
+            'vid': ('django.db.models.fields.IntegerField', [], {'unique': 'True'})
+        }
+    }
+
+    complete_apps = ['firewall']
\ No newline at end of file
diff --git a/circle/firewall/migrations/0012_auto__chg_field_rule_nat_dport__add_field_host_shared_ip.py b/circle/firewall/migrations/0012_auto__chg_field_rule_nat_dport__add_field_host_shared_ip.py
new file mode 100644
index 0000000..c8a3bcb
--- /dev/null
+++ b/circle/firewall/migrations/0012_auto__chg_field_rule_nat_dport__add_field_host_shared_ip.py
@@ -0,0 +1,132 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+
+        # Changing field 'Rule.nat_dport'
+        db.alter_column('firewall_rule', 'nat_dport', self.gf('django.db.models.fields.IntegerField')(null=True))
+        # Adding field 'Host.shared_ip'
+        db.add_column('firewall_host', 'shared_ip',
+                      self.gf('django.db.models.fields.BooleanField')(default=False),
+                      keep_default=False)
+
+
+    def backwards(self, orm):
+
+        # User chose to not deal with backwards NULL issues for 'Rule.nat_dport'
+        raise RuntimeError("Cannot reverse this migration. 'Rule.nat_dport' and its values cannot be restored.")
+        # Deleting field 'Host.shared_ip'
+        db.delete_column('firewall_host', 'shared_ip')
+
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'firewall.firewall': {
+            'Meta': {'object_name': 'Firewall'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.host': {
+            'Meta': {'object_name': 'Host'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Group']", 'null': 'True', 'blank': 'True'}),
+            'hostname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39', 'blank': 'True'}),
+            'location': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'mac': ('firewall.fields.MACAddressField', [], {'unique': 'True', 'max_length': '17'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'pub_ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'}),
+            'shared_ip': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Vlan']"})
+        },
+        'firewall.rule': {
+            'Meta': {'object_name': 'Rule'},
+            'accept': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'direction': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'dport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'extra': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nat': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'nat_dport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'proto': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
+            'r_type': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
+            'sport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'vlan': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.vlan': {
+            'Meta': {'object_name': 'Vlan'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'dhcp_pool': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'domain': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'interface': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'net4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'net6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'prefix4': ('django.db.models.fields.IntegerField', [], {'default': '16'}),
+            'prefix6': ('django.db.models.fields.IntegerField', [], {'default': '80'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'firewall_vlan_related'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['firewall.Rule']"}),
+            'snat_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
+            'snat_to': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'}),
+            'vid': ('django.db.models.fields.IntegerField', [], {'unique': 'True'})
+        }
+    }
+
+    complete_apps = ['firewall']
\ No newline at end of file
diff --git a/circle/firewall/migrations/0013_auto__del_unique_host_pub_ipv4.py b/circle/firewall/migrations/0013_auto__del_unique_host_pub_ipv4.py
new file mode 100644
index 0000000..e29fca4
--- /dev/null
+++ b/circle/firewall/migrations/0013_auto__del_unique_host_pub_ipv4.py
@@ -0,0 +1,124 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        # Removing unique constraint on 'Host', fields ['pub_ipv4']
+        db.delete_unique('firewall_host', ['pub_ipv4'])
+
+
+    def backwards(self, orm):
+        # Adding unique constraint on 'Host', fields ['pub_ipv4']
+        db.create_unique('firewall_host', ['pub_ipv4'])
+
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'firewall.firewall': {
+            'Meta': {'object_name': 'Firewall'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.host': {
+            'Meta': {'object_name': 'Host'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Group']", 'null': 'True', 'blank': 'True'}),
+            'hostname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39', 'blank': 'True'}),
+            'location': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'mac': ('firewall.fields.MACAddressField', [], {'unique': 'True', 'max_length': '17'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'pub_ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'}),
+            'shared_ip': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Vlan']"})
+        },
+        'firewall.rule': {
+            'Meta': {'object_name': 'Rule'},
+            'accept': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'direction': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'dport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'extra': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nat': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'nat_dport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'proto': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
+            'r_type': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
+            'sport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'vlan': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.vlan': {
+            'Meta': {'object_name': 'Vlan'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'dhcp_pool': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'domain': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'interface': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'net4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'net6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'prefix4': ('django.db.models.fields.IntegerField', [], {'default': '16'}),
+            'prefix6': ('django.db.models.fields.IntegerField', [], {'default': '80'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'firewall_vlan_related'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['firewall.Rule']"}),
+            'snat_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
+            'snat_to': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'}),
+            'vid': ('django.db.models.fields.IntegerField', [], {'unique': 'True'})
+        }
+    }
+
+    complete_apps = ['firewall']
\ No newline at end of file
diff --git a/circle/firewall/migrations/0014_auto__chg_field_rule_direction.py b/circle/firewall/migrations/0014_auto__chg_field_rule_direction.py
new file mode 100644
index 0000000..71cc407
--- /dev/null
+++ b/circle/firewall/migrations/0014_auto__chg_field_rule_direction.py
@@ -0,0 +1,124 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+
+        # Changing field 'Rule.direction'
+        db.alter_column('firewall_rule', 'direction', self.gf('django.db.models.fields.CharField')(max_length=1))
+
+    def backwards(self, orm):
+
+        # Changing field 'Rule.direction'
+        db.alter_column('firewall_rule', 'direction', self.gf('django.db.models.fields.BooleanField')())
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'firewall.firewall': {
+            'Meta': {'object_name': 'Firewall'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.host': {
+            'Meta': {'object_name': 'Host'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Group']", 'null': 'True', 'blank': 'True'}),
+            'hostname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39', 'blank': 'True'}),
+            'location': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'mac': ('firewall.fields.MACAddressField', [], {'unique': 'True', 'max_length': '17'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'pub_ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'}),
+            'shared_ip': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Vlan']"})
+        },
+        'firewall.rule': {
+            'Meta': {'object_name': 'Rule'},
+            'accept': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'direction': ('django.db.models.fields.CharField', [], {'max_length': '1'}),
+            'dport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'extra': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nat': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'nat_dport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'proto': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
+            'r_type': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
+            'sport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'vlan': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.vlan': {
+            'Meta': {'object_name': 'Vlan'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'dhcp_pool': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'domain': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'interface': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'net4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'net6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'prefix4': ('django.db.models.fields.IntegerField', [], {'default': '16'}),
+            'prefix6': ('django.db.models.fields.IntegerField', [], {'default': '80'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'firewall_vlan_related'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['firewall.Rule']"}),
+            'snat_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
+            'snat_to': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'}),
+            'vid': ('django.db.models.fields.IntegerField', [], {'unique': 'True'})
+        }
+    }
+
+    complete_apps = ['firewall']
\ No newline at end of file
diff --git a/circle/firewall/migrations/0015_auto__chg_field_host_hostname.py b/circle/firewall/migrations/0015_auto__chg_field_host_hostname.py
new file mode 100644
index 0000000..542771b
--- /dev/null
+++ b/circle/firewall/migrations/0015_auto__chg_field_host_hostname.py
@@ -0,0 +1,124 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+
+        # Changing field 'Host.hostname'
+        db.alter_column('firewall_host', 'hostname', self.gf('django.db.models.fields.CharField')(unique=True, max_length=40))
+
+    def backwards(self, orm):
+
+        # Changing field 'Host.hostname'
+        db.alter_column('firewall_host', 'hostname', self.gf('django.db.models.fields.CharField')(max_length=20, unique=True))
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'firewall.firewall': {
+            'Meta': {'object_name': 'Firewall'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.host': {
+            'Meta': {'object_name': 'Host'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Group']", 'null': 'True', 'blank': 'True'}),
+            'hostname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39', 'blank': 'True'}),
+            'location': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'mac': ('firewall.fields.MACAddressField', [], {'unique': 'True', 'max_length': '17'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'pub_ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'}),
+            'shared_ip': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Vlan']"})
+        },
+        'firewall.rule': {
+            'Meta': {'object_name': 'Rule'},
+            'accept': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'direction': ('django.db.models.fields.CharField', [], {'max_length': '1'}),
+            'dport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'extra': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nat': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'nat_dport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'proto': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
+            'r_type': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
+            'sport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'vlan': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.vlan': {
+            'Meta': {'object_name': 'Vlan'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'dhcp_pool': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'domain': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'interface': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'net4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'net6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'prefix4': ('django.db.models.fields.IntegerField', [], {'default': '16'}),
+            'prefix6': ('django.db.models.fields.IntegerField', [], {'default': '80'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'firewall_vlan_related'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['firewall.Rule']"}),
+            'snat_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
+            'snat_to': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'}),
+            'vid': ('django.db.models.fields.IntegerField', [], {'unique': 'True'})
+        }
+    }
+
+    complete_apps = ['firewall']
\ No newline at end of file
diff --git a/circle/firewall/migrations/0016_auto__add_alias__chg_field_host_ipv6.py b/circle/firewall/migrations/0016_auto__add_alias__chg_field_host_ipv6.py
new file mode 100644
index 0000000..333fb60
--- /dev/null
+++ b/circle/firewall/migrations/0016_auto__add_alias__chg_field_host_ipv6.py
@@ -0,0 +1,141 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        # Adding model 'Alias'
+        db.create_table('firewall_alias', (
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+            ('host', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['firewall.Host'])),
+            ('hostname', self.gf('django.db.models.fields.CharField')(unique=True, max_length=40)),
+        ))
+        db.send_create_signal('firewall', ['Alias'])
+
+
+        # Changing field 'Host.ipv6'
+        db.alter_column('firewall_host', 'ipv6', self.gf('django.db.models.fields.GenericIPAddressField')(max_length=39, unique=True, null=True))
+
+    def backwards(self, orm):
+        # Deleting model 'Alias'
+        db.delete_table('firewall_alias')
+
+
+        # User chose to not deal with backwards NULL issues for 'Host.ipv6'
+        raise RuntimeError("Cannot reverse this migration. 'Host.ipv6' and its values cannot be restored.")
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'firewall.alias': {
+            'Meta': {'object_name': 'Alias'},
+            'host': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Host']"}),
+            'hostname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
+        },
+        'firewall.firewall': {
+            'Meta': {'object_name': 'Firewall'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.host': {
+            'Meta': {'object_name': 'Host'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Group']", 'null': 'True', 'blank': 'True'}),
+            'hostname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
+            'location': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'mac': ('firewall.fields.MACAddressField', [], {'unique': 'True', 'max_length': '17'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'pub_ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'}),
+            'shared_ip': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Vlan']"})
+        },
+        'firewall.rule': {
+            'Meta': {'object_name': 'Rule'},
+            'accept': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'direction': ('django.db.models.fields.CharField', [], {'max_length': '1'}),
+            'dport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'extra': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nat': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'nat_dport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'proto': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
+            'r_type': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
+            'sport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'vlan': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.vlan': {
+            'Meta': {'object_name': 'Vlan'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'dhcp_pool': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'domain': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'interface': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'net4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'net6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'prefix4': ('django.db.models.fields.IntegerField', [], {'default': '16'}),
+            'prefix6': ('django.db.models.fields.IntegerField', [], {'default': '80'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'firewall_vlan_related'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['firewall.Rule']"}),
+            'snat_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
+            'snat_to': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'}),
+            'vid': ('django.db.models.fields.IntegerField', [], {'unique': 'True'})
+        }
+    }
+
+    complete_apps = ['firewall']
\ No newline at end of file
diff --git a/circle/firewall/migrations/0017_auto__del_field_alias_hostname__add_field_alias_alias.py b/circle/firewall/migrations/0017_auto__del_field_alias_hostname__add_field_alias_alias.py
new file mode 100644
index 0000000..f5f55d7
--- /dev/null
+++ b/circle/firewall/migrations/0017_auto__del_field_alias_hostname__add_field_alias_alias.py
@@ -0,0 +1,138 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        # Deleting field 'Alias.hostname'
+        db.delete_column('firewall_alias', 'hostname')
+
+        # Adding field 'Alias.alias'
+        db.add_column('firewall_alias', 'alias',
+                      self.gf('django.db.models.fields.CharField')(default=None, unique=True, max_length=40),
+                      keep_default=False)
+
+
+    def backwards(self, orm):
+
+        # User chose to not deal with backwards NULL issues for 'Alias.hostname'
+        raise RuntimeError("Cannot reverse this migration. 'Alias.hostname' and its values cannot be restored.")
+        # Deleting field 'Alias.alias'
+        db.delete_column('firewall_alias', 'alias')
+
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'firewall.alias': {
+            'Meta': {'object_name': 'Alias'},
+            'alias': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}),
+            'host': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Host']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
+        },
+        'firewall.firewall': {
+            'Meta': {'object_name': 'Firewall'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.host': {
+            'Meta': {'object_name': 'Host'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Group']", 'null': 'True', 'blank': 'True'}),
+            'hostname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
+            'location': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'mac': ('firewall.fields.MACAddressField', [], {'unique': 'True', 'max_length': '17'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'pub_ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'}),
+            'shared_ip': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Vlan']"})
+        },
+        'firewall.rule': {
+            'Meta': {'object_name': 'Rule'},
+            'accept': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'direction': ('django.db.models.fields.CharField', [], {'max_length': '1'}),
+            'dport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'extra': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nat': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'nat_dport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'proto': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
+            'r_type': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
+            'sport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'vlan': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.vlan': {
+            'Meta': {'object_name': 'Vlan'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'dhcp_pool': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'domain': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'interface': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'net4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'net6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'prefix4': ('django.db.models.fields.IntegerField', [], {'default': '16'}),
+            'prefix6': ('django.db.models.fields.IntegerField', [], {'default': '80'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'firewall_vlan_related'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['firewall.Rule']"}),
+            'snat_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
+            'snat_to': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'}),
+            'vid': ('django.db.models.fields.IntegerField', [], {'unique': 'True'})
+        }
+    }
+
+    complete_apps = ['firewall']
\ No newline at end of file
diff --git a/circle/firewall/migrations/0018_auto__add_field_host_reverse.py b/circle/firewall/migrations/0018_auto__add_field_host_reverse.py
new file mode 100644
index 0000000..5ff8261
--- /dev/null
+++ b/circle/firewall/migrations/0018_auto__add_field_host_reverse.py
@@ -0,0 +1,133 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        # Adding field 'Host.reverse'
+        db.add_column('firewall_host', 'reverse',
+                      self.gf('django.db.models.fields.CharField')(max_length=40, unique=True, null=True, blank=True),
+                      keep_default=False)
+
+
+    def backwards(self, orm):
+        # Deleting field 'Host.reverse'
+        db.delete_column('firewall_host', 'reverse')
+
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'firewall.alias': {
+            'Meta': {'object_name': 'Alias'},
+            'alias': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}),
+            'host': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Host']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
+        },
+        'firewall.firewall': {
+            'Meta': {'object_name': 'Firewall'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.host': {
+            'Meta': {'object_name': 'Host'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Group']", 'null': 'True', 'blank': 'True'}),
+            'hostname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
+            'location': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'mac': ('firewall.fields.MACAddressField', [], {'unique': 'True', 'max_length': '17'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'pub_ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
+            'reverse': ('django.db.models.fields.CharField', [], {'max_length': '40', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'}),
+            'shared_ip': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Vlan']"})
+        },
+        'firewall.rule': {
+            'Meta': {'object_name': 'Rule'},
+            'accept': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'direction': ('django.db.models.fields.CharField', [], {'max_length': '1'}),
+            'dport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'extra': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nat': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'nat_dport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'proto': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
+            'r_type': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
+            'sport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'vlan': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.vlan': {
+            'Meta': {'object_name': 'Vlan'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'dhcp_pool': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'domain': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'interface': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'net4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'net6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'prefix4': ('django.db.models.fields.IntegerField', [], {'default': '16'}),
+            'prefix6': ('django.db.models.fields.IntegerField', [], {'default': '80'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'firewall_vlan_related'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['firewall.Rule']"}),
+            'snat_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
+            'snat_to': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'}),
+            'vid': ('django.db.models.fields.IntegerField', [], {'unique': 'True'})
+        }
+    }
+
+    complete_apps = ['firewall']
\ No newline at end of file
diff --git a/circle/firewall/migrations/0019_auto__del_unique_host_reverse.py b/circle/firewall/migrations/0019_auto__del_unique_host_reverse.py
new file mode 100644
index 0000000..ec2e7a6
--- /dev/null
+++ b/circle/firewall/migrations/0019_auto__del_unique_host_reverse.py
@@ -0,0 +1,131 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        # Removing unique constraint on 'Host', fields ['reverse']
+        db.delete_unique('firewall_host', ['reverse'])
+
+
+    def backwards(self, orm):
+        # Adding unique constraint on 'Host', fields ['reverse']
+        db.create_unique('firewall_host', ['reverse'])
+
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'firewall.alias': {
+            'Meta': {'object_name': 'Alias'},
+            'alias': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}),
+            'host': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Host']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
+        },
+        'firewall.firewall': {
+            'Meta': {'object_name': 'Firewall'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.host': {
+            'Meta': {'object_name': 'Host'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Group']", 'null': 'True', 'blank': 'True'}),
+            'hostname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
+            'location': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'mac': ('firewall.fields.MACAddressField', [], {'unique': 'True', 'max_length': '17'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'pub_ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
+            'reverse': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'}),
+            'shared_ip': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Vlan']"})
+        },
+        'firewall.rule': {
+            'Meta': {'object_name': 'Rule'},
+            'accept': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'direction': ('django.db.models.fields.CharField', [], {'max_length': '1'}),
+            'dport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'extra': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nat': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'nat_dport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'proto': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
+            'r_type': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
+            'sport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'vlan': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.vlan': {
+            'Meta': {'object_name': 'Vlan'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'dhcp_pool': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'domain': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'interface': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'net4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'net6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'prefix4': ('django.db.models.fields.IntegerField', [], {'default': '16'}),
+            'prefix6': ('django.db.models.fields.IntegerField', [], {'default': '80'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'firewall_vlan_related'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['firewall.Rule']"}),
+            'snat_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
+            'snat_to': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'}),
+            'vid': ('django.db.models.fields.IntegerField', [], {'unique': 'True'})
+        }
+    }
+
+    complete_apps = ['firewall']
\ No newline at end of file
diff --git a/circle/firewall/migrations/0020_auto__add_setting.py b/circle/firewall/migrations/0020_auto__add_setting.py
new file mode 100644
index 0000000..93cf3f2
--- /dev/null
+++ b/circle/firewall/migrations/0020_auto__add_setting.py
@@ -0,0 +1,142 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        # Adding model 'Setting'
+        db.create_table('firewall_setting', (
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+            ('key', self.gf('django.db.models.fields.CharField')(max_length=32)),
+            ('value', self.gf('django.db.models.fields.CharField')(max_length=200)),
+        ))
+        db.send_create_signal('firewall', ['Setting'])
+
+
+    def backwards(self, orm):
+        # Deleting model 'Setting'
+        db.delete_table('firewall_setting')
+
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'firewall.alias': {
+            'Meta': {'object_name': 'Alias'},
+            'alias': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}),
+            'host': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Host']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
+        },
+        'firewall.firewall': {
+            'Meta': {'object_name': 'Firewall'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.host': {
+            'Meta': {'object_name': 'Host'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Group']", 'null': 'True', 'blank': 'True'}),
+            'hostname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
+            'location': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'mac': ('firewall.fields.MACAddressField', [], {'unique': 'True', 'max_length': '17'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'pub_ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
+            'reverse': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'}),
+            'shared_ip': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Vlan']"})
+        },
+        'firewall.rule': {
+            'Meta': {'object_name': 'Rule'},
+            'accept': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'direction': ('django.db.models.fields.CharField', [], {'max_length': '1'}),
+            'dport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'extra': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nat': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'nat_dport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'proto': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
+            'r_type': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
+            'sport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'vlan': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.setting': {
+            'Meta': {'object_name': 'Setting'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'key': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+            'value': ('django.db.models.fields.CharField', [], {'max_length': '200'})
+        },
+        'firewall.vlan': {
+            'Meta': {'object_name': 'Vlan'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'dhcp_pool': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'domain': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'interface': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'net4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'net6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'prefix4': ('django.db.models.fields.IntegerField', [], {'default': '16'}),
+            'prefix6': ('django.db.models.fields.IntegerField', [], {'default': '80'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'firewall_vlan_related'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['firewall.Rule']"}),
+            'snat_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
+            'snat_to': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'}),
+            'vid': ('django.db.models.fields.IntegerField', [], {'unique': 'True'})
+        }
+    }
+
+    complete_apps = ['firewall']
\ No newline at end of file
diff --git a/circle/firewall/migrations/0021_auto__add_field_host_created_at__add_field_host_modified_at__add_field.py b/circle/firewall/migrations/0021_auto__add_field_host_created_at__add_field_host_modified_at__add_field.py
new file mode 100644
index 0000000..217cbee
--- /dev/null
+++ b/circle/firewall/migrations/0021_auto__add_field_host_created_at__add_field_host_modified_at__add_field.py
@@ -0,0 +1,230 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        # Adding field 'Host.created_at'
+        db.add_column('firewall_host', 'created_at',
+                      self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, default=datetime.datetime(2013, 1, 28, 0, 0), blank=True),
+                      keep_default=False)
+
+        # Adding field 'Host.modified_at'
+        db.add_column('firewall_host', 'modified_at',
+                      self.gf('django.db.models.fields.DateTimeField')(auto_now=True, default=datetime.datetime(2013, 1, 28, 0, 0), blank=True),
+                      keep_default=False)
+
+        # Adding field 'Group.created_at'
+        db.add_column('firewall_group', 'created_at',
+                      self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, default=datetime.datetime(2013, 1, 28, 0, 0), blank=True),
+                      keep_default=False)
+
+        # Adding field 'Group.modified_at'
+        db.add_column('firewall_group', 'modified_at',
+                      self.gf('django.db.models.fields.DateTimeField')(auto_now=True, default=datetime.datetime(2013, 1, 28, 0, 0), blank=True),
+                      keep_default=False)
+
+        # Adding field 'Vlan.created_at'
+        db.add_column('firewall_vlan', 'created_at',
+                      self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, default=datetime.datetime(2013, 1, 28, 0, 0), blank=True),
+                      keep_default=False)
+
+        # Adding field 'Vlan.modified_at'
+        db.add_column('firewall_vlan', 'modified_at',
+                      self.gf('django.db.models.fields.DateTimeField')(auto_now=True, default=datetime.datetime(2013, 1, 28, 0, 0), blank=True),
+                      keep_default=False)
+
+        # Adding field 'Rule.created_at'
+        db.add_column('firewall_rule', 'created_at',
+                      self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, default=datetime.datetime(2013, 1, 28, 0, 0), blank=True),
+                      keep_default=False)
+
+        # Adding field 'Rule.modified_at'
+        db.add_column('firewall_rule', 'modified_at',
+                      self.gf('django.db.models.fields.DateTimeField')(auto_now=True, default=datetime.datetime(2013, 1, 28, 0, 0), blank=True),
+                      keep_default=False)
+
+        # Adding field 'Alias.owner'
+        db.add_column('firewall_alias', 'owner',
+                      self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'], null=True, blank=True),
+                      keep_default=False)
+
+        # Adding field 'Alias.created_at'
+        db.add_column('firewall_alias', 'created_at',
+                      self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, default=datetime.datetime(2013, 1, 28, 0, 0), blank=True),
+                      keep_default=False)
+
+        # Adding field 'Alias.modified_at'
+        db.add_column('firewall_alias', 'modified_at',
+                      self.gf('django.db.models.fields.DateTimeField')(auto_now=True, default=datetime.datetime(2013, 1, 28, 0, 0), blank=True),
+                      keep_default=False)
+
+
+    def backwards(self, orm):
+        # Deleting field 'Host.created_at'
+        db.delete_column('firewall_host', 'created_at')
+
+        # Deleting field 'Host.modified_at'
+        db.delete_column('firewall_host', 'modified_at')
+
+        # Deleting field 'Group.created_at'
+        db.delete_column('firewall_group', 'created_at')
+
+        # Deleting field 'Group.modified_at'
+        db.delete_column('firewall_group', 'modified_at')
+
+        # Deleting field 'Vlan.created_at'
+        db.delete_column('firewall_vlan', 'created_at')
+
+        # Deleting field 'Vlan.modified_at'
+        db.delete_column('firewall_vlan', 'modified_at')
+
+        # Deleting field 'Rule.created_at'
+        db.delete_column('firewall_rule', 'created_at')
+
+        # Deleting field 'Rule.modified_at'
+        db.delete_column('firewall_rule', 'modified_at')
+
+        # Deleting field 'Alias.owner'
+        db.delete_column('firewall_alias', 'owner_id')
+
+        # Deleting field 'Alias.created_at'
+        db.delete_column('firewall_alias', 'created_at')
+
+        # Deleting field 'Alias.modified_at'
+        db.delete_column('firewall_alias', 'modified_at')
+
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'firewall.alias': {
+            'Meta': {'object_name': 'Alias'},
+            'alias': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'host': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Host']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.firewall': {
+            'Meta': {'object_name': 'Firewall'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.group': {
+            'Meta': {'object_name': 'Group'},
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.host': {
+            'Meta': {'object_name': 'Host'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Group']", 'null': 'True', 'blank': 'True'}),
+            'hostname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
+            'location': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'mac': ('firewall.fields.MACAddressField', [], {'unique': 'True', 'max_length': '17'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'pub_ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
+            'reverse': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'}),
+            'shared_ip': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Vlan']"})
+        },
+        'firewall.rule': {
+            'Meta': {'object_name': 'Rule'},
+            'accept': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'direction': ('django.db.models.fields.CharField', [], {'max_length': '1'}),
+            'dport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'extra': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'nat': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'nat_dport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'proto': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
+            'r_type': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
+            'sport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'vlan': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.setting': {
+            'Meta': {'object_name': 'Setting'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'key': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+            'value': ('django.db.models.fields.CharField', [], {'max_length': '200'})
+        },
+        'firewall.vlan': {
+            'Meta': {'object_name': 'Vlan'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'dhcp_pool': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'domain': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'interface': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'net4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'net6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'prefix4': ('django.db.models.fields.IntegerField', [], {'default': '16'}),
+            'prefix6': ('django.db.models.fields.IntegerField', [], {'default': '80'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'firewall_vlan_related'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['firewall.Rule']"}),
+            'snat_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
+            'snat_to': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'}),
+            'vid': ('django.db.models.fields.IntegerField', [], {'unique': 'True'})
+        }
+    }
+
+    complete_apps = ['firewall']
\ No newline at end of file
diff --git a/circle/firewall/migrations/0022_auto__add_vlangroup__add_field_setting_description__add_field_group_de.py b/circle/firewall/migrations/0022_auto__add_vlangroup__add_field_setting_description__add_field_group_de.py
new file mode 100644
index 0000000..8ae2c24
--- /dev/null
+++ b/circle/firewall/migrations/0022_auto__add_vlangroup__add_field_setting_description__add_field_group_de.py
@@ -0,0 +1,298 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        # Adding model 'VlanGroup'
+        db.create_table('firewall_vlangroup', (
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+            ('name', self.gf('django.db.models.fields.CharField')(unique=True, max_length=20)),
+            ('description', self.gf('django.db.models.fields.TextField')(blank=True)),
+            ('owner', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'], null=True, blank=True)),
+            ('created_at', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
+            ('modified_at', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, blank=True)),
+        ))
+        db.send_create_signal('firewall', ['VlanGroup'])
+
+        # Adding M2M table for field vlans on 'VlanGroup'
+        db.create_table('firewall_vlangroup_vlans', (
+            ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
+            ('vlangroup', models.ForeignKey(orm['firewall.vlangroup'], null=False)),
+            ('vlan', models.ForeignKey(orm['firewall.vlan'], null=False))
+        ))
+        db.create_unique('firewall_vlangroup_vlans', ['vlangroup_id', 'vlan_id'])
+
+        # Removing M2M table for field rules on 'Host'
+        db.delete_table('firewall_host_rules')
+
+        # Adding field 'Setting.description'
+        db.add_column('firewall_setting', 'description',
+                      self.gf('django.db.models.fields.TextField')(default='', blank=True),
+                      keep_default=False)
+
+        # Adding field 'Group.description'
+        db.add_column('firewall_group', 'description',
+                      self.gf('django.db.models.fields.TextField')(default='', blank=True),
+                      keep_default=False)
+
+        # Adding field 'Group.owner'
+        db.add_column('firewall_group', 'owner',
+                      self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'], null=True, blank=True),
+                      keep_default=False)
+
+        # Removing M2M table for field rules on 'Group'
+        db.delete_table('firewall_group_rules')
+
+        # Adding field 'Vlan.owner'
+        db.add_column('firewall_vlan', 'owner',
+                      self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'], null=True, blank=True),
+                      keep_default=False)
+
+        # Removing M2M table for field rules on 'Vlan'
+        db.delete_table('firewall_vlan_rules')
+
+        # Adding field 'Rule.foreign_network'
+        db.add_column('firewall_rule', 'foreign_network',
+                      self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='ForeignRules', to=orm['firewall.VlanGroup']),
+                      keep_default=False)
+
+        # Adding field 'Rule.vlan'
+        db.add_column('firewall_rule', 'vlan',
+                      self.gf('django.db.models.fields.related.ForeignKey')(to=orm['firewall.Vlan'], null=True, blank=True),
+                      keep_default=False)
+
+        # Adding field 'Rule.vlangroup'
+        db.add_column('firewall_rule', 'vlangroup',
+                      self.gf('django.db.models.fields.related.ForeignKey')(to=orm['firewall.VlanGroup'], null=True, blank=True),
+                      keep_default=False)
+
+        # Adding field 'Rule.host'
+        db.add_column('firewall_rule', 'host',
+                      self.gf('django.db.models.fields.related.ForeignKey')(to=orm['firewall.Host'], null=True, blank=True),
+                      keep_default=False)
+
+        # Adding field 'Rule.hostgroup'
+        db.add_column('firewall_rule', 'hostgroup',
+                      self.gf('django.db.models.fields.related.ForeignKey')(to=orm['firewall.Group'], null=True, blank=True),
+                      keep_default=False)
+
+        # Removing M2M table for field vlan on 'Rule'
+        db.delete_table('firewall_rule_vlan')
+
+
+    def backwards(self, orm):
+        # Deleting model 'VlanGroup'
+        db.delete_table('firewall_vlangroup')
+
+        # Removing M2M table for field vlans on 'VlanGroup'
+        db.delete_table('firewall_vlangroup_vlans')
+
+        # Adding M2M table for field rules on 'Host'
+        db.create_table('firewall_host_rules', (
+            ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
+            ('host', models.ForeignKey(orm['firewall.host'], null=False)),
+            ('rule', models.ForeignKey(orm['firewall.rule'], null=False))
+        ))
+        db.create_unique('firewall_host_rules', ['host_id', 'rule_id'])
+
+        # Deleting field 'Setting.description'
+        db.delete_column('firewall_setting', 'description')
+
+        # Deleting field 'Group.description'
+        db.delete_column('firewall_group', 'description')
+
+        # Deleting field 'Group.owner'
+        db.delete_column('firewall_group', 'owner_id')
+
+        # Adding M2M table for field rules on 'Group'
+        db.create_table('firewall_group_rules', (
+            ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
+            ('group', models.ForeignKey(orm['firewall.group'], null=False)),
+            ('rule', models.ForeignKey(orm['firewall.rule'], null=False))
+        ))
+        db.create_unique('firewall_group_rules', ['group_id', 'rule_id'])
+
+        # Deleting field 'Vlan.owner'
+        db.delete_column('firewall_vlan', 'owner_id')
+
+        # Adding M2M table for field rules on 'Vlan'
+        db.create_table('firewall_vlan_rules', (
+            ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
+            ('vlan', models.ForeignKey(orm['firewall.vlan'], null=False)),
+            ('rule', models.ForeignKey(orm['firewall.rule'], null=False))
+        ))
+        db.create_unique('firewall_vlan_rules', ['vlan_id', 'rule_id'])
+
+        # Deleting field 'Rule.foreign_network'
+        db.delete_column('firewall_rule', 'foreign_network_id')
+
+        # Deleting field 'Rule.vlan'
+        db.delete_column('firewall_rule', 'vlan_id')
+
+        # Deleting field 'Rule.vlangroup'
+        db.delete_column('firewall_rule', 'vlangroup_id')
+
+        # Deleting field 'Rule.host'
+        db.delete_column('firewall_rule', 'host_id')
+
+        # Deleting field 'Rule.hostgroup'
+        db.delete_column('firewall_rule', 'hostgroup_id')
+
+        # Adding M2M table for field vlan on 'Rule'
+        db.create_table('firewall_rule_vlan', (
+            ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
+            ('rule', models.ForeignKey(orm['firewall.rule'], null=False)),
+            ('vlan', models.ForeignKey(orm['firewall.vlan'], null=False))
+        ))
+        db.create_unique('firewall_rule_vlan', ['rule_id', 'vlan_id'])
+
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'firewall.alias': {
+            'Meta': {'object_name': 'Alias'},
+            'alias': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'host': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Host']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.firewall': {
+            'Meta': {'object_name': 'Firewall'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.group': {
+            'Meta': {'object_name': 'Group'},
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.host': {
+            'Meta': {'object_name': 'Host'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Group']", 'null': 'True', 'blank': 'True'}),
+            'hostname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
+            'location': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'mac': ('firewall.fields.MACAddressField', [], {'unique': 'True', 'max_length': '17'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'pub_ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
+            'reverse': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}),
+            'shared_ip': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Vlan']"})
+        },
+        'firewall.rule': {
+            'Meta': {'object_name': 'Rule'},
+            'accept': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'direction': ('django.db.models.fields.CharField', [], {'max_length': '1'}),
+            'dport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'extra': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'foreign_network': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ForeignRules'", 'to': "orm['firewall.VlanGroup']"}),
+            'host': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Host']", 'null': 'True', 'blank': 'True'}),
+            'hostgroup': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Group']", 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'nat': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'nat_dport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'proto': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
+            'r_type': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
+            'sport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'}),
+            'vlangroup': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.VlanGroup']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.setting': {
+            'Meta': {'object_name': 'Setting'},
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'key': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+            'value': ('django.db.models.fields.CharField', [], {'max_length': '200'})
+        },
+        'firewall.vlan': {
+            'Meta': {'object_name': 'Vlan'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'dhcp_pool': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'domain': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'interface': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'net4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'net6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'prefix4': ('django.db.models.fields.IntegerField', [], {'default': '16'}),
+            'prefix6': ('django.db.models.fields.IntegerField', [], {'default': '80'}),
+            'snat_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
+            'snat_to': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'}),
+            'vid': ('django.db.models.fields.IntegerField', [], {'unique': 'True'})
+        },
+        'firewall.vlangroup': {
+            'Meta': {'object_name': 'VlanGroup'},
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'vlans': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'})
+        }
+    }
+
+    complete_apps = ['firewall']
\ No newline at end of file
diff --git a/circle/firewall/migrations/0023_auto__add_field_rule_firewall.py b/circle/firewall/migrations/0023_auto__add_field_rule_firewall.py
new file mode 100644
index 0000000..1cc3a61
--- /dev/null
+++ b/circle/firewall/migrations/0023_auto__add_field_rule_firewall.py
@@ -0,0 +1,176 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        # Removing M2M table for field rules on 'Firewall'
+        db.delete_table('firewall_firewall_rules')
+
+        # Adding field 'Rule.firewall'
+        db.add_column('firewall_rule', 'firewall',
+                      self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='rules', null=True, to=orm['firewall.Firewall']),
+                      keep_default=False)
+
+
+    def backwards(self, orm):
+        # Adding M2M table for field rules on 'Firewall'
+        db.create_table('firewall_firewall_rules', (
+            ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
+            ('firewall', models.ForeignKey(orm['firewall.firewall'], null=False)),
+            ('rule', models.ForeignKey(orm['firewall.rule'], null=False))
+        ))
+        db.create_unique('firewall_firewall_rules', ['firewall_id', 'rule_id'])
+
+        # Deleting field 'Rule.firewall'
+        db.delete_column('firewall_rule', 'firewall_id')
+
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'firewall.alias': {
+            'Meta': {'object_name': 'Alias'},
+            'alias': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'host': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Host']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.firewall': {
+            'Meta': {'object_name': 'Firewall'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'})
+        },
+        'firewall.group': {
+            'Meta': {'object_name': 'Group'},
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.host': {
+            'Meta': {'object_name': 'Host'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Group']", 'null': 'True', 'blank': 'True'}),
+            'hostname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
+            'location': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'mac': ('firewall.fields.MACAddressField', [], {'unique': 'True', 'max_length': '17'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'pub_ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
+            'reverse': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}),
+            'shared_ip': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Vlan']"})
+        },
+        'firewall.rule': {
+            'Meta': {'object_name': 'Rule'},
+            'accept': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'direction': ('django.db.models.fields.CharField', [], {'max_length': '1'}),
+            'dport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'extra': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'firewall': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.Firewall']"}),
+            'foreign_network': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ForeignRules'", 'to': "orm['firewall.VlanGroup']"}),
+            'host': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.Host']"}),
+            'hostgroup': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.Group']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'nat': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'nat_dport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'proto': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
+            'r_type': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
+            'sport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'vlan': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.Vlan']"}),
+            'vlangroup': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.VlanGroup']"})
+        },
+        'firewall.setting': {
+            'Meta': {'object_name': 'Setting'},
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'key': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+            'value': ('django.db.models.fields.CharField', [], {'max_length': '200'})
+        },
+        'firewall.vlan': {
+            'Meta': {'object_name': 'Vlan'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'dhcp_pool': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'domain': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'interface': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'net4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'net6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'prefix4': ('django.db.models.fields.IntegerField', [], {'default': '16'}),
+            'prefix6': ('django.db.models.fields.IntegerField', [], {'default': '80'}),
+            'snat_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
+            'snat_to': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'}),
+            'vid': ('django.db.models.fields.IntegerField', [], {'unique': 'True'})
+        },
+        'firewall.vlangroup': {
+            'Meta': {'object_name': 'VlanGroup'},
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'vlans': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'})
+        }
+    }
+
+    complete_apps = ['firewall']
\ No newline at end of file
diff --git a/circle/firewall/migrations/0024_auto__add_domain__add_record.py b/circle/firewall/migrations/0024_auto__add_domain__add_record.py
new file mode 100644
index 0000000..25d9ffa
--- /dev/null
+++ b/circle/firewall/migrations/0024_auto__add_domain__add_record.py
@@ -0,0 +1,215 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        # Adding model 'Domain'
+        db.create_table('firewall_domain', (
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+            ('name', self.gf('django.db.models.fields.CharField')(max_length=40)),
+            ('owner', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])),
+            ('created_at', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
+            ('modified_at', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, blank=True)),
+            ('ttl', self.gf('django.db.models.fields.IntegerField')(default=600)),
+            ('description', self.gf('django.db.models.fields.TextField')(blank=True)),
+        ))
+        db.send_create_signal('firewall', ['Domain'])
+
+        # Adding model 'Record'
+        db.create_table('firewall_record', (
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+            ('name', self.gf('django.db.models.fields.CharField')(max_length=40)),
+            ('domain', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['firewall.Domain'])),
+            ('host', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['firewall.Host'], null=True, blank=True)),
+            ('type', self.gf('django.db.models.fields.CharField')(max_length=6)),
+            ('address', self.gf('django.db.models.fields.CharField')(max_length=40)),
+            ('ttl', self.gf('django.db.models.fields.IntegerField')(default=600)),
+            ('owner', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])),
+            ('description', self.gf('django.db.models.fields.TextField')(blank=True)),
+            ('created_at', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
+            ('modified_at', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, blank=True)),
+        ))
+        db.send_create_signal('firewall', ['Record'])
+
+
+    def backwards(self, orm):
+        # Deleting model 'Domain'
+        db.delete_table('firewall_domain')
+
+        # Deleting model 'Record'
+        db.delete_table('firewall_record')
+
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'firewall.alias': {
+            'Meta': {'object_name': 'Alias'},
+            'alias': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'host': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Host']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.domain': {
+            'Meta': {'object_name': 'Domain'},
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'ttl': ('django.db.models.fields.IntegerField', [], {'default': '600'})
+        },
+        'firewall.firewall': {
+            'Meta': {'object_name': 'Firewall'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'})
+        },
+        'firewall.group': {
+            'Meta': {'object_name': 'Group'},
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.host': {
+            'Meta': {'object_name': 'Host'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Group']", 'null': 'True', 'blank': 'True'}),
+            'hostname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
+            'location': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'mac': ('firewall.fields.MACAddressField', [], {'unique': 'True', 'max_length': '17'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'pub_ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
+            'reverse': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}),
+            'shared_ip': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Vlan']"})
+        },
+        'firewall.record': {
+            'Meta': {'object_name': 'Record'},
+            'address': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'domain': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Domain']"}),
+            'host': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Host']", 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'ttl': ('django.db.models.fields.IntegerField', [], {'default': '600'}),
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '6'})
+        },
+        'firewall.rule': {
+            'Meta': {'object_name': 'Rule'},
+            'accept': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'direction': ('django.db.models.fields.CharField', [], {'max_length': '1'}),
+            'dport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'extra': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'firewall': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.Firewall']"}),
+            'foreign_network': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ForeignRules'", 'to': "orm['firewall.VlanGroup']"}),
+            'host': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.Host']"}),
+            'hostgroup': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.Group']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'nat': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'nat_dport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'proto': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
+            'r_type': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
+            'sport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'vlan': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.Vlan']"}),
+            'vlangroup': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.VlanGroup']"})
+        },
+        'firewall.setting': {
+            'Meta': {'object_name': 'Setting'},
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'key': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+            'value': ('django.db.models.fields.CharField', [], {'max_length': '200'})
+        },
+        'firewall.vlan': {
+            'Meta': {'object_name': 'Vlan'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'dhcp_pool': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'domain': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'interface': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'net4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'net6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'prefix4': ('django.db.models.fields.IntegerField', [], {'default': '16'}),
+            'prefix6': ('django.db.models.fields.IntegerField', [], {'default': '80'}),
+            'snat_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
+            'snat_to': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'}),
+            'vid': ('django.db.models.fields.IntegerField', [], {'unique': 'True'})
+        },
+        'firewall.vlangroup': {
+            'Meta': {'object_name': 'VlanGroup'},
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'vlans': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'})
+        }
+    }
+
+    complete_apps = ['firewall']
\ No newline at end of file
diff --git a/circle/firewall/migrations/0025_auto__chg_field_record_address.py b/circle/firewall/migrations/0025_auto__chg_field_record_address.py
new file mode 100644
index 0000000..c99c63b
--- /dev/null
+++ b/circle/firewall/migrations/0025_auto__chg_field_record_address.py
@@ -0,0 +1,187 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+
+        # Changing field 'Record.address'
+        db.alter_column('firewall_record', 'address', self.gf('django.db.models.fields.CharField')(max_length=40, null=True))
+
+    def backwards(self, orm):
+
+        # User chose to not deal with backwards NULL issues for 'Record.address'
+        raise RuntimeError("Cannot reverse this migration. 'Record.address' and its values cannot be restored.")
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'firewall.alias': {
+            'Meta': {'object_name': 'Alias'},
+            'alias': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'host': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Host']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.domain': {
+            'Meta': {'object_name': 'Domain'},
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'ttl': ('django.db.models.fields.IntegerField', [], {'default': '600'})
+        },
+        'firewall.firewall': {
+            'Meta': {'object_name': 'Firewall'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'})
+        },
+        'firewall.group': {
+            'Meta': {'object_name': 'Group'},
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.host': {
+            'Meta': {'object_name': 'Host'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Group']", 'null': 'True', 'blank': 'True'}),
+            'hostname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
+            'location': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'mac': ('firewall.fields.MACAddressField', [], {'unique': 'True', 'max_length': '17'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'pub_ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
+            'reverse': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}),
+            'shared_ip': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Vlan']"})
+        },
+        'firewall.record': {
+            'Meta': {'object_name': 'Record'},
+            'address': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'domain': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Domain']"}),
+            'host': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Host']", 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'ttl': ('django.db.models.fields.IntegerField', [], {'default': '600'}),
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '6'})
+        },
+        'firewall.rule': {
+            'Meta': {'object_name': 'Rule'},
+            'accept': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'direction': ('django.db.models.fields.CharField', [], {'max_length': '1'}),
+            'dport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'extra': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'firewall': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.Firewall']"}),
+            'foreign_network': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ForeignRules'", 'to': "orm['firewall.VlanGroup']"}),
+            'host': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.Host']"}),
+            'hostgroup': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.Group']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'nat': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'nat_dport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'proto': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
+            'r_type': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
+            'sport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'vlan': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.Vlan']"}),
+            'vlangroup': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.VlanGroup']"})
+        },
+        'firewall.setting': {
+            'Meta': {'object_name': 'Setting'},
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'key': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+            'value': ('django.db.models.fields.CharField', [], {'max_length': '200'})
+        },
+        'firewall.vlan': {
+            'Meta': {'object_name': 'Vlan'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'dhcp_pool': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'domain': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'interface': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'net4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'net6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'prefix4': ('django.db.models.fields.IntegerField', [], {'default': '16'}),
+            'prefix6': ('django.db.models.fields.IntegerField', [], {'default': '80'}),
+            'snat_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
+            'snat_to': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'}),
+            'vid': ('django.db.models.fields.IntegerField', [], {'unique': 'True'})
+        },
+        'firewall.vlangroup': {
+            'Meta': {'object_name': 'VlanGroup'},
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'vlans': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'})
+        }
+    }
+
+    complete_apps = ['firewall']
\ No newline at end of file
diff --git a/circle/firewall/migrations/0026_auto__chg_field_record_name.py b/circle/firewall/migrations/0026_auto__chg_field_record_name.py
new file mode 100644
index 0000000..9f93573
--- /dev/null
+++ b/circle/firewall/migrations/0026_auto__chg_field_record_name.py
@@ -0,0 +1,187 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+
+        # Changing field 'Record.name'
+        db.alter_column('firewall_record', 'name', self.gf('django.db.models.fields.CharField')(max_length=40, null=True))
+
+    def backwards(self, orm):
+
+        # User chose to not deal with backwards NULL issues for 'Record.name'
+        raise RuntimeError("Cannot reverse this migration. 'Record.name' and its values cannot be restored.")
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'firewall.alias': {
+            'Meta': {'object_name': 'Alias'},
+            'alias': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'host': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Host']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.domain': {
+            'Meta': {'object_name': 'Domain'},
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'ttl': ('django.db.models.fields.IntegerField', [], {'default': '600'})
+        },
+        'firewall.firewall': {
+            'Meta': {'object_name': 'Firewall'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'})
+        },
+        'firewall.group': {
+            'Meta': {'object_name': 'Group'},
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.host': {
+            'Meta': {'object_name': 'Host'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Group']", 'null': 'True', 'blank': 'True'}),
+            'hostname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
+            'location': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'mac': ('firewall.fields.MACAddressField', [], {'unique': 'True', 'max_length': '17'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'pub_ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
+            'reverse': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}),
+            'shared_ip': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Vlan']"})
+        },
+        'firewall.record': {
+            'Meta': {'object_name': 'Record'},
+            'address': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'domain': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Domain']"}),
+            'host': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Host']", 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'ttl': ('django.db.models.fields.IntegerField', [], {'default': '600'}),
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '6'})
+        },
+        'firewall.rule': {
+            'Meta': {'object_name': 'Rule'},
+            'accept': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'direction': ('django.db.models.fields.CharField', [], {'max_length': '1'}),
+            'dport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'extra': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'firewall': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.Firewall']"}),
+            'foreign_network': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ForeignRules'", 'to': "orm['firewall.VlanGroup']"}),
+            'host': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.Host']"}),
+            'hostgroup': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.Group']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'nat': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'nat_dport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'proto': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
+            'r_type': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
+            'sport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'vlan': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.Vlan']"}),
+            'vlangroup': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.VlanGroup']"})
+        },
+        'firewall.setting': {
+            'Meta': {'object_name': 'Setting'},
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'key': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+            'value': ('django.db.models.fields.CharField', [], {'max_length': '200'})
+        },
+        'firewall.vlan': {
+            'Meta': {'object_name': 'Vlan'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'dhcp_pool': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'domain': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'interface': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'net4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'net6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'prefix4': ('django.db.models.fields.IntegerField', [], {'default': '16'}),
+            'prefix6': ('django.db.models.fields.IntegerField', [], {'default': '80'}),
+            'snat_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
+            'snat_to': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'}),
+            'vid': ('django.db.models.fields.IntegerField', [], {'unique': 'True'})
+        },
+        'firewall.vlangroup': {
+            'Meta': {'object_name': 'VlanGroup'},
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'vlans': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'})
+        }
+    }
+
+    complete_apps = ['firewall']
\ No newline at end of file
diff --git a/circle/firewall/migrations/0027_auto__add_field_vlan_reverse_domain.py b/circle/firewall/migrations/0027_auto__add_field_vlan_reverse_domain.py
new file mode 100644
index 0000000..9bc7c18
--- /dev/null
+++ b/circle/firewall/migrations/0027_auto__add_field_vlan_reverse_domain.py
@@ -0,0 +1,190 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        # Adding field 'Vlan.reverse_domain'
+        db.add_column('firewall_vlan', 'reverse_domain',
+                      self.gf('django.db.models.fields.TextField')(default=None),
+                      keep_default=False)
+
+
+    def backwards(self, orm):
+        # Deleting field 'Vlan.reverse_domain'
+        db.delete_column('firewall_vlan', 'reverse_domain')
+
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'firewall.alias': {
+            'Meta': {'object_name': 'Alias'},
+            'alias': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'host': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Host']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.domain': {
+            'Meta': {'object_name': 'Domain'},
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'ttl': ('django.db.models.fields.IntegerField', [], {'default': '600'})
+        },
+        'firewall.firewall': {
+            'Meta': {'object_name': 'Firewall'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'})
+        },
+        'firewall.group': {
+            'Meta': {'object_name': 'Group'},
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.host': {
+            'Meta': {'object_name': 'Host'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Group']", 'null': 'True', 'blank': 'True'}),
+            'hostname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
+            'location': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'mac': ('firewall.fields.MACAddressField', [], {'unique': 'True', 'max_length': '17'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'pub_ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
+            'reverse': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}),
+            'shared_ip': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Vlan']"})
+        },
+        'firewall.record': {
+            'Meta': {'object_name': 'Record'},
+            'address': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'domain': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Domain']"}),
+            'host': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Host']", 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'ttl': ('django.db.models.fields.IntegerField', [], {'default': '600'}),
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '6'})
+        },
+        'firewall.rule': {
+            'Meta': {'object_name': 'Rule'},
+            'accept': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'direction': ('django.db.models.fields.CharField', [], {'max_length': '1'}),
+            'dport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'extra': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'firewall': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.Firewall']"}),
+            'foreign_network': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ForeignRules'", 'to': "orm['firewall.VlanGroup']"}),
+            'host': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.Host']"}),
+            'hostgroup': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.Group']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'nat': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'nat_dport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'proto': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
+            'r_type': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
+            'sport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'vlan': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.Vlan']"}),
+            'vlangroup': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.VlanGroup']"})
+        },
+        'firewall.setting': {
+            'Meta': {'object_name': 'Setting'},
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'key': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+            'value': ('django.db.models.fields.CharField', [], {'max_length': '200'})
+        },
+        'firewall.vlan': {
+            'Meta': {'object_name': 'Vlan'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'dhcp_pool': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'domain': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'interface': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'net4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'net6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'prefix4': ('django.db.models.fields.IntegerField', [], {'default': '16'}),
+            'prefix6': ('django.db.models.fields.IntegerField', [], {'default': '80'}),
+            'reverse_domain': ('django.db.models.fields.TextField', [], {}),
+            'snat_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
+            'snat_to': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'}),
+            'vid': ('django.db.models.fields.IntegerField', [], {'unique': 'True'})
+        },
+        'firewall.vlangroup': {
+            'Meta': {'object_name': 'VlanGroup'},
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'vlans': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'})
+        }
+    }
+
+    complete_apps = ['firewall']
\ No newline at end of file
diff --git a/circle/firewall/migrations/0028_auto__del_field_vlan_domain.py b/circle/firewall/migrations/0028_auto__del_field_vlan_domain.py
new file mode 100644
index 0000000..8060e5d
--- /dev/null
+++ b/circle/firewall/migrations/0028_auto__del_field_vlan_domain.py
@@ -0,0 +1,189 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        # Deleting field 'Vlan.domain'
+        db.delete_column('firewall_vlan', 'domain')
+
+
+    def backwards(self, orm):
+        # Adding field 'Vlan.domain'
+        db.add_column('firewall_vlan', 'domain',
+                      self.gf('django.db.models.fields.TextField')(default='', blank=True),
+                      keep_default=False)
+
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'firewall.alias': {
+            'Meta': {'object_name': 'Alias'},
+            'alias': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'host': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Host']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.domain': {
+            'Meta': {'object_name': 'Domain'},
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'ttl': ('django.db.models.fields.IntegerField', [], {'default': '600'})
+        },
+        'firewall.firewall': {
+            'Meta': {'object_name': 'Firewall'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'})
+        },
+        'firewall.group': {
+            'Meta': {'object_name': 'Group'},
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.host': {
+            'Meta': {'object_name': 'Host'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Group']", 'null': 'True', 'blank': 'True'}),
+            'hostname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
+            'location': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'mac': ('firewall.fields.MACAddressField', [], {'unique': 'True', 'max_length': '17'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'pub_ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
+            'reverse': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}),
+            'shared_ip': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Vlan']"})
+        },
+        'firewall.record': {
+            'Meta': {'object_name': 'Record'},
+            'address': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'domain': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Domain']"}),
+            'host': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Host']", 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'ttl': ('django.db.models.fields.IntegerField', [], {'default': '600'}),
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '6'})
+        },
+        'firewall.rule': {
+            'Meta': {'object_name': 'Rule'},
+            'accept': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'direction': ('django.db.models.fields.CharField', [], {'max_length': '1'}),
+            'dport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'extra': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'firewall': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.Firewall']"}),
+            'foreign_network': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ForeignRules'", 'to': "orm['firewall.VlanGroup']"}),
+            'host': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.Host']"}),
+            'hostgroup': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.Group']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'nat': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'nat_dport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'proto': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
+            'r_type': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
+            'sport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'vlan': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.Vlan']"}),
+            'vlangroup': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.VlanGroup']"})
+        },
+        'firewall.setting': {
+            'Meta': {'object_name': 'Setting'},
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'key': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+            'value': ('django.db.models.fields.CharField', [], {'max_length': '200'})
+        },
+        'firewall.vlan': {
+            'Meta': {'object_name': 'Vlan'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'dhcp_pool': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'interface': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'net4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'net6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'prefix4': ('django.db.models.fields.IntegerField', [], {'default': '16'}),
+            'prefix6': ('django.db.models.fields.IntegerField', [], {'default': '80'}),
+            'reverse_domain': ('django.db.models.fields.TextField', [], {}),
+            'snat_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
+            'snat_to': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'}),
+            'vid': ('django.db.models.fields.IntegerField', [], {'unique': 'True'})
+        },
+        'firewall.vlangroup': {
+            'Meta': {'object_name': 'VlanGroup'},
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'vlans': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'})
+        }
+    }
+
+    complete_apps = ['firewall']
\ No newline at end of file
diff --git a/circle/firewall/migrations/0029_auto__add_field_vlan_domain.py b/circle/firewall/migrations/0029_auto__add_field_vlan_domain.py
new file mode 100644
index 0000000..cfd7fcb
--- /dev/null
+++ b/circle/firewall/migrations/0029_auto__add_field_vlan_domain.py
@@ -0,0 +1,190 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        # Adding field 'Vlan.domain'
+        db.add_column('firewall_vlan', 'domain',
+                      self.gf('django.db.models.fields.related.ForeignKey')(default=None, to=orm['firewall.Domain']),
+                      keep_default=False)
+
+
+    def backwards(self, orm):
+        # Deleting field 'Vlan.domain'
+        db.delete_column('firewall_vlan', 'domain_id')
+
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'firewall.alias': {
+            'Meta': {'object_name': 'Alias'},
+            'alias': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'host': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Host']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.domain': {
+            'Meta': {'object_name': 'Domain'},
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'ttl': ('django.db.models.fields.IntegerField', [], {'default': '600'})
+        },
+        'firewall.firewall': {
+            'Meta': {'object_name': 'Firewall'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'})
+        },
+        'firewall.group': {
+            'Meta': {'object_name': 'Group'},
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.host': {
+            'Meta': {'object_name': 'Host'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Group']", 'null': 'True', 'blank': 'True'}),
+            'hostname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
+            'location': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'mac': ('firewall.fields.MACAddressField', [], {'unique': 'True', 'max_length': '17'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'pub_ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
+            'reverse': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}),
+            'shared_ip': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Vlan']"})
+        },
+        'firewall.record': {
+            'Meta': {'object_name': 'Record'},
+            'address': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'domain': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Domain']"}),
+            'host': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Host']", 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'ttl': ('django.db.models.fields.IntegerField', [], {'default': '600'}),
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '6'})
+        },
+        'firewall.rule': {
+            'Meta': {'object_name': 'Rule'},
+            'accept': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'direction': ('django.db.models.fields.CharField', [], {'max_length': '1'}),
+            'dport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'extra': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'firewall': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.Firewall']"}),
+            'foreign_network': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ForeignRules'", 'to': "orm['firewall.VlanGroup']"}),
+            'host': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.Host']"}),
+            'hostgroup': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.Group']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'nat': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'nat_dport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'proto': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
+            'r_type': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
+            'sport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'vlan': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.Vlan']"}),
+            'vlangroup': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.VlanGroup']"})
+        },
+        'firewall.setting': {
+            'Meta': {'object_name': 'Setting'},
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'key': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+            'value': ('django.db.models.fields.CharField', [], {'max_length': '200'})
+        },
+        'firewall.vlan': {
+            'Meta': {'object_name': 'Vlan'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'dhcp_pool': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'domain': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Domain']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'interface': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'net4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'net6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'prefix4': ('django.db.models.fields.IntegerField', [], {'default': '16'}),
+            'prefix6': ('django.db.models.fields.IntegerField', [], {'default': '80'}),
+            'reverse_domain': ('django.db.models.fields.TextField', [], {}),
+            'snat_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
+            'snat_to': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'}),
+            'vid': ('django.db.models.fields.IntegerField', [], {'unique': 'True'})
+        },
+        'firewall.vlangroup': {
+            'Meta': {'object_name': 'VlanGroup'},
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'vlans': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'})
+        }
+    }
+
+    complete_apps = ['firewall']
\ No newline at end of file
diff --git a/circle/firewall/migrations/0030_auto__del_setting__del_alias__add_blacklist.py b/circle/firewall/migrations/0030_auto__del_setting__del_alias__add_blacklist.py
new file mode 100644
index 0000000..8995adf
--- /dev/null
+++ b/circle/firewall/migrations/0030_auto__del_setting__del_alias__add_blacklist.py
@@ -0,0 +1,213 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        # Deleting model 'Setting'
+        db.delete_table('firewall_setting')
+
+        # Deleting model 'Alias'
+        db.delete_table('firewall_alias')
+
+        # Adding model 'Blacklist'
+        db.create_table('firewall_blacklist', (
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+            ('ipv4', self.gf('django.db.models.fields.GenericIPAddressField')(unique=True, max_length=39)),
+            ('reason', self.gf('django.db.models.fields.TextField')(blank=True)),
+            ('created_at', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
+            ('modified_at', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, blank=True)),
+        ))
+        db.send_create_signal('firewall', ['Blacklist'])
+
+
+    def backwards(self, orm):
+        # Adding model 'Setting'
+        db.create_table('firewall_setting', (
+            ('value', self.gf('django.db.models.fields.CharField')(max_length=200)),
+            ('description', self.gf('django.db.models.fields.TextField')(blank=True)),
+            ('key', self.gf('django.db.models.fields.CharField')(max_length=32)),
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+        ))
+        db.send_create_signal('firewall', ['Setting'])
+
+        # Adding model 'Alias'
+        db.create_table('firewall_alias', (
+            ('created_at', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
+            ('modified_at', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, blank=True)),
+            ('alias', self.gf('django.db.models.fields.CharField')(max_length=40, unique=True)),
+            ('host', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['firewall.Host'])),
+            ('owner', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'], null=True, blank=True)),
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+        ))
+        db.send_create_signal('firewall', ['Alias'])
+
+        # Deleting model 'Blacklist'
+        db.delete_table('firewall_blacklist')
+
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'firewall.blacklist': {
+            'Meta': {'object_name': 'Blacklist'},
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'reason': ('django.db.models.fields.TextField', [], {'blank': 'True'})
+        },
+        'firewall.domain': {
+            'Meta': {'object_name': 'Domain'},
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'ttl': ('django.db.models.fields.IntegerField', [], {'default': '600'})
+        },
+        'firewall.firewall': {
+            'Meta': {'object_name': 'Firewall'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'})
+        },
+        'firewall.group': {
+            'Meta': {'object_name': 'Group'},
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.host': {
+            'Meta': {'object_name': 'Host'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Group']", 'null': 'True', 'blank': 'True'}),
+            'hostname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
+            'location': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'mac': ('firewall.fields.MACAddressField', [], {'unique': 'True', 'max_length': '17'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'pub_ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
+            'reverse': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}),
+            'shared_ip': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Vlan']"})
+        },
+        'firewall.record': {
+            'Meta': {'object_name': 'Record'},
+            'address': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'domain': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Domain']"}),
+            'host': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Host']", 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'ttl': ('django.db.models.fields.IntegerField', [], {'default': '600'}),
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '6'})
+        },
+        'firewall.rule': {
+            'Meta': {'object_name': 'Rule'},
+            'accept': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'direction': ('django.db.models.fields.CharField', [], {'max_length': '1'}),
+            'dport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'extra': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'firewall': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.Firewall']"}),
+            'foreign_network': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ForeignRules'", 'to': "orm['firewall.VlanGroup']"}),
+            'host': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.Host']"}),
+            'hostgroup': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.Group']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'nat': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'nat_dport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'proto': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
+            'r_type': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
+            'sport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'vlan': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.Vlan']"}),
+            'vlangroup': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.VlanGroup']"})
+        },
+        'firewall.vlan': {
+            'Meta': {'object_name': 'Vlan'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'dhcp_pool': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'domain': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Domain']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'interface': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'net4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'net6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'prefix4': ('django.db.models.fields.IntegerField', [], {'default': '16'}),
+            'prefix6': ('django.db.models.fields.IntegerField', [], {'default': '80'}),
+            'reverse_domain': ('django.db.models.fields.TextField', [], {}),
+            'snat_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
+            'snat_to': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'}),
+            'vid': ('django.db.models.fields.IntegerField', [], {'unique': 'True'})
+        },
+        'firewall.vlangroup': {
+            'Meta': {'object_name': 'VlanGroup'},
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'vlans': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'})
+        }
+    }
+
+    complete_apps = ['firewall']
\ No newline at end of file
diff --git a/circle/firewall/migrations/0031_auto__add_field_blacklist_snort_message__add_field_blacklist_type.py b/circle/firewall/migrations/0031_auto__add_field_blacklist_snort_message__add_field_blacklist_type.py
new file mode 100644
index 0000000..39bdac0
--- /dev/null
+++ b/circle/firewall/migrations/0031_auto__add_field_blacklist_snort_message__add_field_blacklist_type.py
@@ -0,0 +1,192 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        # Adding field 'Blacklist.snort_message'
+        db.add_column('firewall_blacklist', 'snort_message',
+                      self.gf('django.db.models.fields.TextField')(default='', blank=True),
+                      keep_default=False)
+
+        # Adding field 'Blacklist.type'
+        db.add_column('firewall_blacklist', 'type',
+                      self.gf('django.db.models.fields.CharField')(default='tempban', max_length=10),
+                      keep_default=False)
+
+
+    def backwards(self, orm):
+        # Deleting field 'Blacklist.snort_message'
+        db.delete_column('firewall_blacklist', 'snort_message')
+
+        # Deleting field 'Blacklist.type'
+        db.delete_column('firewall_blacklist', 'type')
+
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'firewall.blacklist': {
+            'Meta': {'object_name': 'Blacklist'},
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'reason': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'snort_message': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'type': ('django.db.models.fields.CharField', [], {'default': "'tempban'", 'max_length': '10'})
+        },
+        'firewall.domain': {
+            'Meta': {'object_name': 'Domain'},
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'ttl': ('django.db.models.fields.IntegerField', [], {'default': '600'})
+        },
+        'firewall.firewall': {
+            'Meta': {'object_name': 'Firewall'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'})
+        },
+        'firewall.group': {
+            'Meta': {'object_name': 'Group'},
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.host': {
+            'Meta': {'object_name': 'Host'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Group']", 'null': 'True', 'blank': 'True'}),
+            'hostname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
+            'location': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'mac': ('firewall.fields.MACAddressField', [], {'unique': 'True', 'max_length': '17'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'pub_ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
+            'reverse': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}),
+            'shared_ip': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Vlan']"})
+        },
+        'firewall.record': {
+            'Meta': {'object_name': 'Record'},
+            'address': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'domain': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Domain']"}),
+            'host': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Host']", 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'ttl': ('django.db.models.fields.IntegerField', [], {'default': '600'}),
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '6'})
+        },
+        'firewall.rule': {
+            'Meta': {'object_name': 'Rule'},
+            'accept': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'direction': ('django.db.models.fields.CharField', [], {'max_length': '1'}),
+            'dport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'extra': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'firewall': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.Firewall']"}),
+            'foreign_network': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ForeignRules'", 'to': "orm['firewall.VlanGroup']"}),
+            'host': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.Host']"}),
+            'hostgroup': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.Group']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'nat': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'nat_dport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'proto': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
+            'r_type': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
+            'sport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'vlan': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.Vlan']"}),
+            'vlangroup': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.VlanGroup']"})
+        },
+        'firewall.vlan': {
+            'Meta': {'object_name': 'Vlan'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'dhcp_pool': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'domain': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Domain']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'interface': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'net4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'net6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'prefix4': ('django.db.models.fields.IntegerField', [], {'default': '16'}),
+            'prefix6': ('django.db.models.fields.IntegerField', [], {'default': '80'}),
+            'reverse_domain': ('django.db.models.fields.TextField', [], {}),
+            'snat_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
+            'snat_to': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'}),
+            'vid': ('django.db.models.fields.IntegerField', [], {'unique': 'True'})
+        },
+        'firewall.vlangroup': {
+            'Meta': {'object_name': 'VlanGroup'},
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'vlans': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'})
+        }
+    }
+
+    complete_apps = ['firewall']
\ No newline at end of file
diff --git a/circle/firewall/migrations/0032_auto__add_field_blacklist_host.py b/circle/firewall/migrations/0032_auto__add_field_blacklist_host.py
new file mode 100644
index 0000000..6ee2f5e
--- /dev/null
+++ b/circle/firewall/migrations/0032_auto__add_field_blacklist_host.py
@@ -0,0 +1,185 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        # Adding field 'Blacklist.host'
+        db.add_column('firewall_blacklist', 'host',
+                      self.gf('django.db.models.fields.related.ForeignKey')(to=orm['firewall.Host'], null=True, blank=True),
+                      keep_default=False)
+
+
+    def backwards(self, orm):
+        # Deleting field 'Blacklist.host'
+        db.delete_column('firewall_blacklist', 'host_id')
+
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'firewall.blacklist': {
+            'Meta': {'object_name': 'Blacklist'},
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'host': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Host']", 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'reason': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'snort_message': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'type': ('django.db.models.fields.CharField', [], {'default': "'tempban'", 'max_length': '10'})
+        },
+        'firewall.domain': {
+            'Meta': {'object_name': 'Domain'},
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'ttl': ('django.db.models.fields.IntegerField', [], {'default': '600'})
+        },
+        'firewall.firewall': {
+            'Meta': {'object_name': 'Firewall'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'})
+        },
+        'firewall.group': {
+            'Meta': {'object_name': 'Group'},
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'})
+        },
+        'firewall.host': {
+            'Meta': {'object_name': 'Host'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Group']", 'null': 'True', 'blank': 'True'}),
+            'hostname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
+            'location': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'mac': ('firewall.fields.MACAddressField', [], {'unique': 'True', 'max_length': '17'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'pub_ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
+            'reverse': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}),
+            'shared_ip': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Vlan']"})
+        },
+        'firewall.record': {
+            'Meta': {'object_name': 'Record'},
+            'address': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'domain': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Domain']"}),
+            'host': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Host']", 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'ttl': ('django.db.models.fields.IntegerField', [], {'default': '600'}),
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '6'})
+        },
+        'firewall.rule': {
+            'Meta': {'object_name': 'Rule'},
+            'accept': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'direction': ('django.db.models.fields.CharField', [], {'max_length': '1'}),
+            'dport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'extra': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'firewall': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.Firewall']"}),
+            'foreign_network': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ForeignRules'", 'to': "orm['firewall.VlanGroup']"}),
+            'host': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.Host']"}),
+            'hostgroup': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.Group']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'nat': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'nat_dport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'proto': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
+            'r_type': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
+            'sport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'vlan': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.Vlan']"}),
+            'vlangroup': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.VlanGroup']"})
+        },
+        'firewall.vlan': {
+            'Meta': {'object_name': 'Vlan'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'dhcp_pool': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'domain': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Domain']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'interface': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'net4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'net6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'prefix4': ('django.db.models.fields.IntegerField', [], {'default': '16'}),
+            'prefix6': ('django.db.models.fields.IntegerField', [], {'default': '80'}),
+            'reverse_domain': ('django.db.models.fields.TextField', [], {}),
+            'snat_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
+            'snat_to': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'}),
+            'vid': ('django.db.models.fields.IntegerField', [], {'unique': 'True'})
+        },
+        'firewall.vlangroup': {
+            'Meta': {'object_name': 'VlanGroup'},
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'vlans': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'})
+        }
+    }
+
+    complete_apps = ['firewall']
\ No newline at end of file
diff --git a/circle/firewall/migrations/__init__.py b/circle/firewall/migrations/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/circle/firewall/migrations/__init__.py
diff --git a/circle/firewall/models.py b/circle/firewall/models.py
new file mode 100644
index 0000000..1508d9e
--- /dev/null
+++ b/circle/firewall/models.py
@@ -0,0 +1,434 @@
+# -*- coding: utf8 -*-
+
+from django.contrib.auth.models import User
+from django.db import models
+from django.forms import fields, ValidationError
+from django.utils.translation import ugettext_lazy as _
+from firewall.fields import *
+from south.modelsinspector import add_introspection_rules
+from django.core.validators import MinValueValidator, MaxValueValidator
+import django.conf
+from django.db.models.signals import post_save
+import re
+import random
+
+settings = django.conf.settings.FIREWALL_SETTINGS
+class Rule(models.Model):
+    """
+    Common firewall rule
+
+    Rule can be applied to: Host, Firewall, Vlan
+
+    """
+    CHOICES_type = (('host', 'host'), ('firewall', 'firewall'),
+            ('vlan', 'vlan'))
+    CHOICES_proto = (('tcp', 'tcp'), ('udp', 'udp'), ('icmp', 'icmp'))
+    CHOICES_dir = (('0', 'out'), ('1', 'in'))
+
+    direction = models.CharField(max_length=1, choices=CHOICES_dir,
+            blank=False)
+    description = models.TextField(blank=True)
+    foreign_network = models.ForeignKey('VlanGroup',
+            related_name="ForeignRules")
+    dport = models.IntegerField(blank=True, null=True,
+            validators=[MinValueValidator(1), MaxValueValidator(65535)])
+    sport = models.IntegerField(blank=True, null=True,
+            validators=[MinValueValidator(1), MaxValueValidator(65535)])
+    proto = models.CharField(max_length=10, choices=CHOICES_proto,
+            blank=True, null=True)
+    extra = models.TextField(blank=True)
+    accept = models.BooleanField(default=False)
+    owner = models.ForeignKey(User, blank=True, null=True)
+    r_type = models.CharField(max_length=10, choices=CHOICES_type)
+    nat = models.BooleanField(default=False)
+    nat_dport = models.IntegerField(blank=True, null=True,
+            validators=[MinValueValidator(1), MaxValueValidator(65535)])
+    created_at = models.DateTimeField(auto_now_add=True)
+    modified_at = models.DateTimeField(auto_now=True)
+
+    vlan = models.ForeignKey('Vlan', related_name="rules", blank=True,
+            null=True)
+    vlangroup = models.ForeignKey('VlanGroup', related_name="rules",
+            blank=True, null=True)
+    host = models.ForeignKey('Host', related_name="rules", blank=True,
+            null=True)
+    hostgroup = models.ForeignKey('Group', related_name="rules",
+            blank=True, null=True)
+    firewall = models.ForeignKey('Firewall', related_name="rules",
+            blank=True, null=True)
+
+    def __unicode__(self):
+        return self.desc()
+
+    def clean(self):
+        fields = [self.vlan, self.vlangroup, self.host, self.hostgroup,
+                self.firewall]
+        selected_fields = [field for field in fields if field]
+        if len(selected_fields) > 1:
+            raise ValidationError(_('Only one field can be selected.'))
+
+    def desc(self):
+        return u'[%(type)s] %(src)s ▸ %(dst)s %(para)s %(desc)s' % {
+            'type': self.r_type,
+            'src': (unicode(self.foreign_network) if self.direction == '1'
+                else self.r_type),
+            'dst': (self.r_type if self.direction == '1'
+                else unicode(self.foreign_network)),
+            'para': ((("proto=%s " % self.proto) if self.proto else '') +
+                     (("sport=%s " % self.sport) if self.sport else '') +
+                     (("dport=%s " % self.dport) if self.dport else '')),
+            'desc': self.description}
+
+class Vlan(models.Model):
+    vid = models.IntegerField(unique=True)
+    name = models.CharField(max_length=20, unique=True,
+            validators=[val_alfanum])
+    prefix4 = models.IntegerField(default=16)
+    prefix6 = models.IntegerField(default=80)
+    interface = models.CharField(max_length=20, unique=True)
+    net4 = models.GenericIPAddressField(protocol='ipv4', unique=True)
+    net6 = models.GenericIPAddressField(protocol='ipv6', unique=True)
+    ipv4 = models.GenericIPAddressField(protocol='ipv4', unique=True)
+    ipv6 = models.GenericIPAddressField(protocol='ipv6', unique=True)
+    snat_ip = models.GenericIPAddressField(protocol='ipv4', blank=True,
+            null=True)
+    snat_to = models.ManyToManyField('self', symmetrical=False, blank=True,
+            null=True)
+    description = models.TextField(blank=True)
+    comment = models.TextField(blank=True)
+    domain = models.ForeignKey('Domain')
+    reverse_domain = models.TextField(validators=[val_reverse_domain])
+    dhcp_pool = models.TextField(blank=True)
+    created_at = models.DateTimeField(auto_now_add=True)
+    owner = models.ForeignKey(User, blank=True, null=True)
+    modified_at = models.DateTimeField(auto_now=True)
+
+    def __unicode__(self):
+        return self.name
+
+    def net_ipv6(self):
+        return self.net6 + "/" + unicode(self.prefix6)
+
+    def net_ipv4(self):
+        return self.net4 + "/" + unicode(self.prefix4)
+
+class VlanGroup(models.Model):
+    name = models.CharField(max_length=20, unique=True)
+    vlans = models.ManyToManyField('Vlan', symmetrical=False, blank=True,
+            null=True)
+    description = models.TextField(blank=True)
+    owner = models.ForeignKey(User, blank=True, null=True)
+    created_at = models.DateTimeField(auto_now_add=True)
+    modified_at = models.DateTimeField(auto_now=True)
+
+    def __unicode__(self):
+        return self.name
+
+class Group(models.Model):
+    name = models.CharField(max_length=20, unique=True)
+    description = models.TextField(blank=True)
+    owner = models.ForeignKey(User, blank=True, null=True)
+    created_at = models.DateTimeField(auto_now_add=True)
+    modified_at = models.DateTimeField(auto_now=True)
+
+    def __unicode__(self):
+        return self.name
+
+class Host(models.Model):
+    hostname = models.CharField(max_length=40, unique=True,
+            validators=[val_alfanum])
+    reverse = models.CharField(max_length=40, validators=[val_domain],
+            blank=True, null=True)
+    mac = MACAddressField(unique=True)
+    ipv4 = models.GenericIPAddressField(protocol='ipv4', unique=True)
+    pub_ipv4 = models.GenericIPAddressField(protocol='ipv4', blank=True,
+            null=True)
+    ipv6 = models.GenericIPAddressField(protocol='ipv6', unique=True,
+            blank=True, null=True)
+    shared_ip = models.BooleanField(default=False)
+    description = models.TextField(blank=True)
+    comment = models.TextField(blank=True)
+    location = models.TextField(blank=True)
+    vlan = models.ForeignKey('Vlan')
+    owner = models.ForeignKey(User)
+    groups = models.ManyToManyField('Group', symmetrical=False, blank=True,
+            null=True)
+    created_at = models.DateTimeField(auto_now_add=True)
+    modified_at = models.DateTimeField(auto_now=True)
+
+    def __unicode__(self):
+        return self.hostname
+
+    def save(self, *args, **kwargs):
+        id = self.id
+        if not self.id and self.ipv6 == "auto":
+            self.ipv6 = ipv4_2_ipv6(self.ipv4)
+        if (not self.shared_ip and self.pub_ipv4 and Host.objects.
+                exclude(id=self.id).filter(pub_ipv4=self.pub_ipv4)):
+            raise ValidationError(_("If shared_ip has been checked, "
+                "pub_ipv4 has to be unique."))
+        if Host.objects.exclude(id=self.id).filter(pub_ipv4=self.ipv4):
+            raise ValidationError(_("You can't use another host's NAT'd "
+                "address as your own IPv4."))
+        self.full_clean()
+        super(Host, self).save(*args, **kwargs)
+        if not id:
+            Record(domain=self.vlan.domain, host=self, type='A',
+                    owner=self.owner).save()
+            if self.ipv6:
+                Record(domain=self.vlan.domain, host=self, type='AAAA',
+                        owner=self.owner).save()
+
+    def enable_net(self):
+        self.groups.add(Group.objects.get(name="netezhet"))
+
+    def add_port(self, proto, public=None, private=None):
+        proto = "tcp" if proto == "tcp" else "udp"
+        if self.shared_ip:
+            used_ports = Rule.objects.filter(host__pub_ipv4=self.pub_ipv4,
+                    nat=True, proto=proto).values_list('dport', flat=True)
+
+            if public is None:
+                public = random.randint(1024, 21000)
+                if public in used_ports:
+                    for i in range(1024, 21000) + range(24000, 65535):
+                        if i not in used_ports:
+                            public = i
+                            break
+                    else:
+                        raise ValidationError(_("Port %s %s is already in use.") %
+                                (proto, public))
+
+            else:
+                if public < 1024:
+                    raise ValidationError(_("Only ports above 1024 can be used."))
+                if public in used_ports:
+                    raise ValidationError(_("Port %s %s is already in use.") %
+                            (proto, public))
+
+            rule = Rule(direction='1', owner=self.owner, dport=public,
+                    proto=proto, nat=True, accept=True, r_type="host",
+                    nat_dport=private, host=self, foreign_network=VlanGroup.
+                        objects.get(name=settings["default_vlangroup"]))
+        else:
+            if self.rules.filter(proto=proto, dport=public):
+                raise ValidationError(_("Port %s %s is already in use.") %
+                    (proto, public))
+            rule = Rule(direction='1', owner=self.owner, dport=public,
+                    proto=proto, nat=False, accept=True, r_type="host",
+                    host=self, foreign_network=VlanGroup.objects
+                        .get(name=settings["default_vlangroup"]))
+
+        rule.full_clean()
+        rule.save()
+
+    def del_port(self, proto, private):
+        if self.shared_ip:
+            self.rules.filter(owner=self.owner, proto=proto, host=self,
+                nat_dport=private).delete()
+        else:
+            self.rules.filter(owner=self.owner, proto=proto, host=self,
+                dport=private).delete()
+
+    def get_hostname(self, proto):
+        try:
+            if proto == 'ipv6':
+                res = self.record_set.filter(type='AAAA')
+            elif proto == 'ipv4':
+                if self.shared_ip:
+                    res = Record.objects.filter(type='A',
+                            address=self.pub_ipv4)
+                else:
+                    res = self.record_set.filter(type='A')
+            return unicode(res[0].get_data()['name'])
+        except:
+#            raise
+            if self.shared_ip:
+                return self.pub_ipv4
+            else:
+                return self.ipv4
+
+    def list_ports(self):
+        retval = []
+        for rule in self.rules.filter(owner=self.owner):
+            private = rule.nat_dport if self.shared_ip else rule.dport
+            forward = {
+                'proto': rule.proto,
+                'private': private,
+            }
+            if self.shared_ip:
+                public4 = rule.dport
+                public6 = rule.nat_dport
+            else:
+                public4 = public6 = rule.dport
+
+            if True:      # ipv4
+                forward['ipv4'] = {
+                    'host': self.get_hostname(proto='ipv4'),
+                    'port': public4,
+                }
+            if self.ipv6: # ipv6
+                forward['ipv6'] = {
+                    'host': self.get_hostname(proto='ipv6'),
+                    'port': public6,
+                }
+            retval.append(forward)
+        return retval
+
+    def get_fqdn(self):
+        return self.hostname + u'.' + unicode(self.vlan.domain)
+
+
+class Firewall(models.Model):
+    name = models.CharField(max_length=20, unique=True)
+
+    def __unicode__(self):
+        return self.name
+
+class Domain(models.Model):
+    name = models.CharField(max_length=40, validators=[val_domain])
+    owner = models.ForeignKey(User)
+    created_at = models.DateTimeField(auto_now_add=True)
+    modified_at = models.DateTimeField(auto_now=True)
+    ttl = models.IntegerField(default=600)
+    description = models.TextField(blank=True)
+
+    def __unicode__(self):
+        return self.name
+
+class Record(models.Model):
+    CHOICES_type = (('A', 'A'), ('CNAME', 'CNAME'), ('AAAA', 'AAAA'),
+            ('MX', 'MX'), ('NS', 'NS'), ('PTR', 'PTR'), ('TXT', 'TXT'))
+    name = models.CharField(max_length=40, validators=[val_domain],
+            blank=True, null=True)
+    domain = models.ForeignKey('Domain')
+    host = models.ForeignKey('Host', blank=True, null=True)
+    type = models.CharField(max_length=6, choices=CHOICES_type)
+    address = models.CharField(max_length=40, blank=True, null=True)
+    ttl = models.IntegerField(default=600)
+    owner = models.ForeignKey(User)
+    description = models.TextField(blank=True)
+    created_at = models.DateTimeField(auto_now_add=True)
+    modified_at = models.DateTimeField(auto_now=True)
+
+    def __unicode__(self):
+        return self.desc()
+
+    def desc(self):
+        a = self.get_data()
+        return (u' '.join([a['name'], a['type'], a['address']])
+                if a else _('(empty)'))
+
+    def save(self, *args, **kwargs):
+        self.full_clean()
+        super(Record, self).save(*args, **kwargs)
+
+    def clean(self):
+        if self.name:
+            self.name = self.name.rstrip(".")    # remove trailing dots
+
+        if self.host:
+            if self.type in ['A', 'AAAA']:
+                if self.address:
+                    raise ValidationError(_("Can't specify address for "
+                        "A or AAAA records if host is set!"))
+                if self.name:
+                    raise ValidationError(_("Can't specify name for "
+                        "A or AAAA records if host is set!"))
+            elif self.type == 'CNAME':
+                if not self.name:
+                    raise ValidationError(_("Name must be specified for "
+                        "CNAME records if host is set!"))
+                if self.address:
+                    raise ValidationError(_("Can't specify address for "
+                        "CNAME records if host is set!"))
+        else:    # if self.host is None
+            if not self.address:
+                raise ValidationError(_("Address must be specified!"))
+
+            if self.type == 'A':
+                val_ipv4(self.address)
+            elif self.type == 'AAAA':
+                val_ipv6(self.address)
+            elif self.type in ['CNAME', 'NS', 'PTR', 'TXT']:
+                val_domain(self.address)
+            elif self.type == 'MX':
+                mx = self.address.split(':', 1)
+                if not (len(mx) == 2 and mx[0].isdigit() and
+                        domain_re.match(mx[1])):
+                    raise ValidationError(_("Bad address format. "
+                        "Should be: <priority>:<hostname>"))
+            else:
+                raise ValidationError(_("Unknown record type."))
+    def get_name(self):
+        return self.__get_name()
+    def __get_name(self):
+        if self.host and self.type != 'MX':
+            if self.type in ['A', 'AAAA']:
+                return self.host.get_fqdn()
+            elif self.type == 'CNAME':
+                return self.name + '.' + unicode(self.domain)
+            else:
+                return self.name
+        else:    # if self.host is None
+            if self.name:
+                return self.name + '.' + unicode(self.domain)
+            else:
+                return unicode(self.domain)
+
+    def __get_address(self):
+        if self.host:
+            if self.type == 'A':
+                return (self.host.pub_ipv4
+                        if self.host.pub_ipv4 and not self.host.shared_ip
+                        else self.host.ipv4)
+            elif self.type == 'AAAA':
+                return self.host.ipv6
+            elif self.type == 'CNAME':
+                return self.host.get_fqdn()
+        # otherwise:
+        return self.address
+
+    def get_data(self):
+        name = self.__get_name()
+        address = self.__get_address()
+        if self.host and self.type == 'AAAA' and not self.host.ipv6:
+            return None
+        elif not address or not name:
+            return None
+        else:
+            return {'name': name,
+                    'type': self.type,
+                    'ttl': self.ttl,
+                    'address': address}
+
+class Blacklist(models.Model):
+    CHOICES_type = (('permban', 'permanent ban'), ('tempban', 'temporary ban'), ('whitelist', 'whitelist'), ('tempwhite', 'tempwhite'))
+    ipv4 = models.GenericIPAddressField(protocol='ipv4', unique=True)
+    host = models.ForeignKey('Host', blank=True, null=True)
+    reason = models.TextField(blank=True)
+    snort_message = models.TextField(blank=True)
+    type = models.CharField(max_length=10, choices=CHOICES_type, default='tempban')
+    created_at = models.DateTimeField(auto_now_add=True)
+    modified_at = models.DateTimeField(auto_now=True)
+
+    def save(self, *args, **kwargs):
+        self.full_clean()
+        super(Blacklist, self).save(*args, **kwargs)
+    def __unicode__(self):
+        return self.ipv4
+
+def send_task(sender, instance, created, **kwargs):
+    from firewall.tasks import ReloadTask
+    ReloadTask.apply_async(args=[sender.__name__])
+
+
+post_save.connect(send_task, sender=Host)
+post_save.connect(send_task, sender=Rule)
+post_save.connect(send_task, sender=Domain)
+post_save.connect(send_task, sender=Record)
+post_save.connect(send_task, sender=Vlan)
+post_save.connect(send_task, sender=Firewall)
+post_save.connect(send_task, sender=Group)
+post_save.connect(send_task, sender=Host)
+post_save.connect(send_task, sender=Blacklist)
diff --git a/circle/firewall/tasks.py b/circle/firewall/tasks.py
new file mode 100644
index 0000000..7735cbf
--- /dev/null
+++ b/circle/firewall/tasks.py
@@ -0,0 +1,67 @@
+from celery.task import Task, PeriodicTask
+import celery
+from django.core.cache import cache
+import os
+import time
+from firewall.fw import *
+import django.conf
+
+settings = django.conf.settings.FIREWALL_SETTINGS
+
+@celery.task
+def reload_dns_task(data):
+    pass
+@celery.task
+def reload_firewall_task(data4, data6):
+    pass
+@celery.task
+def reload_dhcp_task(data):
+    pass
+@celery.task
+def reload_blacklist_task(data):
+    pass
+
+class Periodic(PeriodicTask):
+    run_every = timedelta(seconds=10)
+
+    def run(self, **kwargs):
+
+        if cache.get('dns_lock'):
+            cache.delete("dns_lock")
+            reload_dns_task.delay(dns())
+            print "dns ujratoltese kesz"
+
+        if cache.get('dhcp_lock'):
+            cache.delete("dhcp_lock")
+            reload_dhcp_task.delay(dhcp())
+            print "dhcp ujratoltese kesz"
+
+        if cache.get('firewall_lock'):
+            cache.delete("firewall_lock")
+            ipv4 = Firewall().get()
+            ipv6 = Firewall(True).get()
+            reload_firewall_task.delay(ipv4, ipv6)
+            print "firewall ujratoltese kesz"
+
+        if cache.get('blacklist_lock'):
+            cache.delete("blacklist_lock")
+            reload_blacklist_task.delay(list(ipset()))
+            print "blacklist ujratoltese kesz"
+
+class ReloadTask(Task):
+    def run(self, type='Host'):
+
+        if type in ["Host", "Records", "Domain", "Vlan"]:
+            cache.add("dns_lock", "true", 30)
+
+        if type == "Host":
+            cache.add("dhcp_lock", "true", 30)
+
+        if type in ["Host", "Rule", "Firewall"]:
+            cache.add("firewall_lock", "true", 30)
+
+        if type == "Blacklist":
+            cache.add("blacklist_lock", "true", 30)
+
+        print type
+
diff --git a/circle/firewall/tests.py b/circle/firewall/tests.py
new file mode 100644
index 0000000..5ab4383
--- /dev/null
+++ b/circle/firewall/tests.py
@@ -0,0 +1,34 @@
+from django.test import TestCase
+from admin import HostAdmin
+
+class MockInstance:
+    def __init__(self, groups):
+        self.groups = MockGroups(groups)
+
+class MockGroup:
+    def __init__(self, name):
+        self.name = name
+
+class MockGroups:
+    def __init__(self, groups):
+        self.groups = groups
+
+    def all(self):
+        return self.groups
+
+class HostAdminTestCase(TestCase):
+    def test_no_groups(self):
+        instance = MockInstance([])
+        l = HostAdmin.list_groups(instance)
+        self.assertEqual(l, "")
+
+    def test_sigle_group(self):
+        instance = MockInstance([MockGroup("alma")])
+        l = HostAdmin.list_groups(instance)
+        self.assertEqual(l, "alma")
+
+    def test_multiple_groups(self):
+        instance = MockInstance([MockGroup("alma"),
+            MockGroup("korte"), MockGroup("szilva")])
+        l = HostAdmin.list_groups(instance)
+        self.assertEqual(l, "alma, korte, szilva")
diff --git a/circle/firewall/views.py b/circle/firewall/views.py
new file mode 100644
index 0000000..9b1923a
--- /dev/null
+++ b/circle/firewall/views.py
@@ -0,0 +1,111 @@
+import base64
+import datetime
+import json
+import re
+import sys
+
+from django.conf import settings
+from django.db import IntegrityError
+from django.http import HttpResponse
+from django.shortcuts import render_to_response
+from django.template.loader import render_to_string
+from django.utils import translation
+from django.utils.timezone import utc
+from django.utils.translation import ugettext_lazy as _
+from django.views.decorators.csrf import csrf_exempt
+from django.views.decorators.http import require_POST
+
+from celery.task.control import inspect
+from tasks import *
+
+from firewall.fw import *
+from firewall.models import *
+from one.tasks import SendMailTask
+
+def reload_firewall(request):
+    if request.user.is_authenticated():
+        if request.user.is_superuser:
+            html = (_("Dear %s, you've signed in as administrator!<br />"
+                      "Reloading in 10 seconds...") % request.user.username)
+            ReloadTask.delay()
+        else:
+            html = (_("Dear %s, you've signed in!") % request.user.username)
+    else:
+        html = _("Dear anonymous, you've not signed in yet!")
+    return HttpResponse(html)
+
+@csrf_exempt
+@require_POST
+def firewall_api(request):
+    try:
+        data=json.loads(base64.b64decode(request.POST["data"]))
+        command = request.POST["command"]
+        if data["password"] != "bdmegintelrontottaanetet":
+            raise Exception(_("Wrong password."))
+
+        if command == "blacklist":
+            obj, created = Blacklist.objects.get_or_create(ipv4=data["ip"])
+            obj.reason=data["reason"]
+            obj.snort_message=data["snort_message"]
+            if created:
+                try:
+                    obj.host = models.Host.objects.get(ipv4=data["ip"])
+                    user = obj.host.owner
+                    lang = user.person_set.all()[0].language
+                    translation.activate(lang)
+                    msg = render_to_string('mails/notification-ban-now.txt',
+                            { 'user': user,
+                              'bl': obj,
+                              'instance:': obj.host.instance_set.get(),
+                              'url': settings.CLOUD_URL} )
+                    SendMailTask.delay(to=obj.host.owner.email, subject='[IK Cloud] %s' % obj.host.instance_set.get().name, msg=msg, sender=u'cloud@ik.bme.hu')
+                except (Host.DoesNotExist, ValidationError, IntegrityError, AttributeError):
+                    pass
+            print obj.modified_at + datetime.timedelta(minutes=5)
+            print datetime.datetime.utcnow().replace(tzinfo=utc)
+            if obj.type == 'tempwhite' and obj.modified_at + datetime.timedelta(minutes=1) < datetime.datetime.utcnow().replace(tzinfo=utc):
+                obj.type = 'tempban'
+            obj.save()
+            return HttpResponse(unicode(_("OK")))
+
+        if not (data["vlan"] == "vm-net" or data["vlan"] == "war"):
+            raise Exception(_("Only vm-net and war can be used."))
+
+        data["hostname"] = re.sub(r' ', '_', data["hostname"])
+
+        if command == "create":
+            data["owner"] = "opennebula"
+            owner = auth.models.User.objects.get(username=data["owner"])
+            host = models.Host(hostname=data["hostname"],
+                    vlan=models.Vlan.objects.get(name=data["vlan"]),
+                    mac=data["mac"], ipv4=data["ip"], owner=owner,
+                    description=data["description"], pub_ipv4=models.
+                        Vlan.objects.get(name=data["vlan"]).snat_ip,
+                    shared_ip=True)
+            host.full_clean()
+            host.save()
+
+            host.enable_net()
+
+            for p in data["portforward"]:
+                host.add_port(proto=p["proto"],
+                        public=int(p["public_port"]),
+                        private=int(p["private_port"]))
+
+        elif command == "destroy":
+            data["owner"] = "opennebula"
+            print data["hostname"]
+            owner = auth.models.User.objects.get(username=data["owner"])
+            host = models.Host.objects.get(hostname=data["hostname"],
+                    owner=owner)
+
+            host.delete()
+        else:
+            raise Exception(_("Unknown command."))
+
+    except (ValidationError, IntegrityError, AttributeError, Exception) as e:
+        return HttpResponse(_("Something went wrong!\n%s\n") % e)
+    except:
+        return HttpResponse(_("Something went wrong!\n"))
+
+    return HttpResponse(unicode(_("OK")))
diff --git a/circle/manager/__init__.py b/circle/manager/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/circle/manager/__init__.py
diff --git a/circle/manager/manager.py b/circle/manager/manager.py
new file mode 100755
index 0000000..d27cd83
--- /dev/null
+++ b/circle/manager/manager.py
@@ -0,0 +1,63 @@
+#!/usr/bin/env python
+
+from mancelery import celery
+from celery import current_task
+
+import scheduler
+
+
+@celery.task
+def deploy(instance):
+    '''Create new virtual machine from VM class.
+    '''
+    # Get info from scheduler (free space, node with enough cpu and ram)
+    current_task.update_state(state='PENDING')
+    instance.node = scheduler.get_node()
+
+    # Create hard drives (storage)
+    current_task.update_state(state='PREPARE')
+    for disk in instance.disks:
+        disk.deploy()
+
+    # Create context
+    instance.create_context()
+
+    # Create machine (vmdriver)
+    current_task.update_state(state='DEPLOY VM')
+    instance.deploy_task()
+
+    # Estabilish network connection (vmdriver)
+    current_task.update_state(state='DEPLOY NET')
+    instance.deploy_net()
+    # Resume machine (vmdriver)
+    current_task.update_state(state='BOOT')
+    instance.resume()
+    pass
+
+
+def delete():
+    pass
+
+
+def save_as():
+    pass
+
+
+def suspend():
+    pass
+
+
+def resume():
+    pass
+
+
+def restart():
+    pass
+
+
+def reset():
+    pass
+
+
+def migrate():
+    pass
diff --git a/circle/manager/mancelery.py b/circle/manager/mancelery.py
new file mode 100755
index 0000000..bfa8787
--- /dev/null
+++ b/circle/manager/mancelery.py
@@ -0,0 +1,19 @@
+#!/usr/bin/env python
+
+from celery import Celery
+from kombu import Queue, Exchange
+from socket import gethostname
+
+
+HOSTNAME = gethostname()
+
+celery = Celery('manager', backend='amqp',
+                broker='amqp://cloud:test@10.9.1.31/vmdriver',
+                include=['vmdriver_stub'])
+
+celery.conf.update(
+    CELERY_QUEUES=(
+        Queue(HOSTNAME + '.man', Exchange(
+            'manager', type='direct'), routing_key="manager"),
+    )
+)
diff --git a/circle/manager/scheduler.py b/circle/manager/scheduler.py
new file mode 100644
index 0000000..03937a3
--- /dev/null
+++ b/circle/manager/scheduler.py
@@ -0,0 +1,2 @@
+def get_node():
+    pass
diff --git a/circle/storage/__init__.py b/circle/storage/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/circle/storage/__init__.py
diff --git a/circle/storage/admin.py b/circle/storage/admin.py
new file mode 100644
index 0000000..1e01d03
--- /dev/null
+++ b/circle/storage/admin.py
@@ -0,0 +1,16 @@
+from django import contrib
+# from django.utils.translation import ugettext_lazy as _
+
+from .models import Disk, DataStore
+
+
+class DiskAdmin(contrib.admin.ModelAdmin):
+    list_display = ('name', 'datastore')
+
+
+class DataStoreAdmin(contrib.admin.ModelAdmin):
+    list_display = ('name', 'path')
+
+
+contrib.admin.site.register(Disk, DiskAdmin)
+contrib.admin.site.register(DataStore, DataStoreAdmin)
diff --git a/circle/storage/migrations/0001_initial.py b/circle/storage/migrations/0001_initial.py
new file mode 100644
index 0000000..16ba799
--- /dev/null
+++ b/circle/storage/migrations/0001_initial.py
@@ -0,0 +1,44 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        # Adding model 'Disk'
+        db.create_table('storage_disk', (
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+            ('name', self.gf('django.db.models.fields.CharField')(unique=True, max_length=100)),
+            ('path', self.gf('django.db.models.fields.CharField')(unique=True, max_length=200)),
+            ('format', self.gf('django.db.models.fields.CharField')(max_length=10)),
+            ('size', self.gf('django.db.models.fields.IntegerField')()),
+            ('type', self.gf('django.db.models.fields.CharField')(max_length=10)),
+            ('base', self.gf('django.db.models.fields.related.ForeignKey')(related_name='snapshots', to=orm['storage.Disk'])),
+            ('original_parent', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['storage.Disk'])),
+        ))
+        db.send_create_signal('storage', ['Disk'])
+
+
+    def backwards(self, orm):
+        # Deleting model 'Disk'
+        db.delete_table('storage_disk')
+
+
+    models = {
+        'storage.disk': {
+            'Meta': {'ordering': "['name']", 'object_name': 'Disk'},
+            'base': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'snapshots'", 'to': "orm['storage.Disk']"}),
+            'format': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
+            'original_parent': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['storage.Disk']"}),
+            'path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '200'}),
+            'size': ('django.db.models.fields.IntegerField', [], {}),
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '10'})
+        }
+    }
+
+    complete_apps = ['storage']
\ No newline at end of file
diff --git a/circle/storage/migrations/0002_auto__chg_field_disk_original_parent__chg_field_disk_base.py b/circle/storage/migrations/0002_auto__chg_field_disk_original_parent__chg_field_disk_base.py
new file mode 100644
index 0000000..d36d46a
--- /dev/null
+++ b/circle/storage/migrations/0002_auto__chg_field_disk_original_parent__chg_field_disk_base.py
@@ -0,0 +1,40 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+
+        # Changing field 'Disk.original_parent'
+        db.alter_column('storage_disk', 'original_parent_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['storage.Disk'], null=True))
+
+        # Changing field 'Disk.base'
+        db.alter_column('storage_disk', 'base_id', self.gf('django.db.models.fields.related.ForeignKey')(null=True, to=orm['storage.Disk']))
+
+    def backwards(self, orm):
+
+        # User chose to not deal with backwards NULL issues for 'Disk.original_parent'
+        raise RuntimeError("Cannot reverse this migration. 'Disk.original_parent' and its values cannot be restored.")
+
+        # User chose to not deal with backwards NULL issues for 'Disk.base'
+        raise RuntimeError("Cannot reverse this migration. 'Disk.base' and its values cannot be restored.")
+
+    models = {
+        'storage.disk': {
+            'Meta': {'ordering': "['name']", 'object_name': 'Disk'},
+            'base': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'snapshots'", 'null': 'True', 'to': "orm['storage.Disk']"}),
+            'format': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
+            'original_parent': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['storage.Disk']", 'null': 'True', 'blank': 'True'}),
+            'path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '200'}),
+            'size': ('django.db.models.fields.IntegerField', [], {}),
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '10'})
+        }
+    }
+
+    complete_apps = ['storage']
\ No newline at end of file
diff --git a/circle/storage/migrations/0003_auto__add_datastore__del_field_disk_path__add_field_disk_datastore.py b/circle/storage/migrations/0003_auto__add_datastore__del_field_disk_path__add_field_disk_datastore.py
new file mode 100644
index 0000000..5aa40c9
--- /dev/null
+++ b/circle/storage/migrations/0003_auto__add_datastore__del_field_disk_path__add_field_disk_datastore.py
@@ -0,0 +1,59 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        # Adding model 'DataStore'
+        db.create_table('storage_datastore', (
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+            ('name', self.gf('django.db.models.fields.CharField')(unique=True, max_length=100)),
+            ('path', self.gf('django.db.models.fields.CharField')(unique=True, max_length=200)),
+        ))
+        db.send_create_signal('storage', ['DataStore'])
+
+        # Deleting field 'Disk.path'
+        db.delete_column('storage_disk', 'path')
+
+        # Adding field 'Disk.datastore'
+        db.add_column('storage_disk', 'datastore',
+                      self.gf('django.db.models.fields.related.ForeignKey')(default=None, to=orm['storage.DataStore']),
+                      keep_default=False)
+
+
+    def backwards(self, orm):
+        # Deleting model 'DataStore'
+        db.delete_table('storage_datastore')
+
+
+        # User chose to not deal with backwards NULL issues for 'Disk.path'
+        raise RuntimeError("Cannot reverse this migration. 'Disk.path' and its values cannot be restored.")
+        # Deleting field 'Disk.datastore'
+        db.delete_column('storage_disk', 'datastore_id')
+
+
+    models = {
+        'storage.datastore': {
+            'Meta': {'ordering': "['name']", 'object_name': 'DataStore'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
+            'path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '200'})
+        },
+        'storage.disk': {
+            'Meta': {'ordering': "['name']", 'object_name': 'Disk'},
+            'base': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'snapshots'", 'null': 'True', 'to': "orm['storage.Disk']"}),
+            'datastore': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['storage.DataStore']"}),
+            'format': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
+            'original_parent': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['storage.Disk']", 'null': 'True', 'blank': 'True'}),
+            'size': ('django.db.models.fields.IntegerField', [], {}),
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '10'})
+        }
+    }
+
+    complete_apps = ['storage']
\ No newline at end of file
diff --git a/circle/storage/migrations/0004_auto__add_field_disk_created.py b/circle/storage/migrations/0004_auto__add_field_disk_created.py
new file mode 100644
index 0000000..e094d9e
--- /dev/null
+++ b/circle/storage/migrations/0004_auto__add_field_disk_created.py
@@ -0,0 +1,43 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        # Adding field 'Disk.created'
+        db.add_column('storage_disk', 'created',
+                      self.gf('django.db.models.fields.BooleanField')(default=False),
+                      keep_default=False)
+
+
+    def backwards(self, orm):
+        # Deleting field 'Disk.created'
+        db.delete_column('storage_disk', 'created')
+
+
+    models = {
+        'storage.datastore': {
+            'Meta': {'ordering': "['name']", 'object_name': 'DataStore'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
+            'path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '200'})
+        },
+        'storage.disk': {
+            'Meta': {'ordering': "['name']", 'object_name': 'Disk'},
+            'base': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'snapshots'", 'null': 'True', 'to': "orm['storage.Disk']"}),
+            'created': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'datastore': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['storage.DataStore']"}),
+            'format': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
+            'original_parent': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['storage.Disk']", 'null': 'True', 'blank': 'True'}),
+            'size': ('django.db.models.fields.IntegerField', [], {}),
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '10'})
+        }
+    }
+
+    complete_apps = ['storage']
\ No newline at end of file
diff --git a/circle/storage/migrations/__init__.py b/circle/storage/migrations/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/circle/storage/migrations/__init__.py
diff --git a/circle/storage/models.py b/circle/storage/models.py
new file mode 100644
index 0000000..2641d17
--- /dev/null
+++ b/circle/storage/models.py
@@ -0,0 +1,145 @@
+# coding=utf-8
+
+import logging
+import jsonpickle
+import json
+from django.db import models, transaction
+from django.utils.translation import ugettext_lazy as _
+from django.db.models.signals import post_save, post_delete
+from model_utils.models import TimeStampedModel
+
+from .tasks import StorageDriver
+
+logger = logging.getLogger(__name__)
+
+
+class DataStore(models.Model):
+    '''
+
+    '''
+    name = models.CharField(max_length=100, unique=True,
+                            verbose_name=_('name'))
+    path = models.CharField(max_length=200, unique=True,
+                            verbose_name=_('path'))
+
+    class Meta:
+        ordering = ['name']
+        verbose_name = _('datastore')
+        verbose_name_plural = _('datastores')
+
+    def __unicode__(self):
+        return u'%s (%s)' % (self.name, self.path)
+
+
+class Disk(TimeStampedModel):
+    """Virtual disks."""
+    FORMATS = [('qcow2', 'qcow2'), ('raw', 'raw'), ('iso', 'iso')]
+    TYPES = [('snapshot', 'snapshot'), ('normal', 'normal')]
+    name = models.CharField(max_length=100, unique=True,
+                            verbose_name=_('name'))
+    datastore = models.ForeignKey('DataStore')
+    format = models.CharField(max_length=10, choices=FORMATS)
+    size = models.IntegerField()
+    type = models.CharField(max_length=10, choices=TYPES)
+    base = models.ForeignKey('self', blank=True, null=True,
+                             related_name='derivatives')
+    ready = models.BooleanField(default=False)
+    dev_num = models.CharField(max_length=1, verbose_name="device number")
+
+    class Meta:
+        ordering = ['name']
+        verbose_name = _('disk')
+        verbose_name_plural = _('disks')
+
+    def get_exclusive(self):
+        """Get an instance of the disk for exclusive usage.
+
+        It might mean copying the disk, creating a snapshot or creating a
+        symbolic link to a read-only image.
+        """
+        # TODO implement (or call) logic
+        return self
+
+    @property
+    def device_type(self):
+        return {
+            'qcow2': 'vd',
+            'raw': 'vd',
+            'iso': 'hd',
+        }[self.format]
+
+    def get_vmdisk_desc(self):
+        return {
+            'source': self.datastore.path + '/' + self.name,
+            'driver_type': self.format,
+            'driver_cache': 'default',
+            'target_device': self.device_type + self.dev_num
+        }
+
+
+    def to_json(self):
+        self.base_name = self.base.name if self.base else None
+        self.dir = self.datastore.path
+        return jsonpickle.encode(self, unpicklable=True)
+
+    def __unicode__(self):
+        return u"%s (#%d)" % (self.name, self.id)
+
+    @classmethod
+    def create_signal(cls, sender, instance, created, **kwargs):
+        if not instance.created:
+            StorageDriver.create_disk.delay(instance.to_json()).get()
+            instance.created = True
+            instance.save()
+
+    @classmethod
+    def delete_signal(cls, sender, instance, using, **kwargs):
+        StorageDriver.delete_disk.delay(instance.to_json()).get()
+
+    @classmethod
+    def update_disk(cls, disk):
+        name = disk['name']
+        modified = False
+        try:
+            base = cls.objects.get(name=disk['base_name'])
+        except cls.DoesNotExist:
+            base = None
+
+        try:
+            d = cls.objects.get(name=name)
+        except Disk.DoesNotExist:
+            d = Disk(name=name,
+                     created=True,
+                     datastore=DataStore.objects.get(path=disk['dir']),
+                     format=disk['format'],
+                     type=disk['type'])
+            modified = True
+
+        if d.size != disk['size'] or d.base != base:
+            d.size = disk['size']
+            d.base = base
+            modified = True
+
+        if modified:
+            d.full_clean()
+            d.save()
+
+    @classmethod
+    def update_disks(cls, delete=True):
+        """Get and register virtual disks from storage driver."""
+        try:
+            json_data = StorageDriver.list_disks.delay().get(timeout=10)
+            disks = json.loads(json_data)
+        except:
+            return
+        with transaction.commit_on_success():
+            l = []
+            for disk in disks:
+                print disk
+                cls.update_disk(disk)
+                l.append(disk['name'])
+            if delete:
+                cls.objects.exclude(name__in=l).delete()
+
+post_save.connect(Disk.create_signal, sender=Disk)
+post_delete.connect(Disk.delete_signal, sender=Disk)
diff --git a/circle/storage/tasks.py b/circle/storage/tasks.py
new file mode 100644
index 0000000..357a189
--- /dev/null
+++ b/circle/storage/tasks.py
@@ -0,0 +1,24 @@
+import celery
+from celery.contrib.methods import task_method
+
+import logging
+
+logger = logging.getLogger(__name__)
+
+
+class StorageDriver:
+    @celery.task(filter=task_method, name='storagedriver.list_disks')
+    def list_disks():
+        pass
+
+    @celery.task(filter=task_method, name='storagedriver.create_disk')
+    def create_disk(json_data):
+        pass
+
+    @celery.task(filter=task_method, name='storagedriver.delete_disk')
+    def delete_disk(json_data):
+        pass
+
+    @celery.task(filter=task_method, name='storagedriver.get_disk')
+    def get_disk(json_data):
+        pass
diff --git a/circle/storage/tests.py b/circle/storage/tests.py
new file mode 100644
index 0000000..501deb7
--- /dev/null
+++ b/circle/storage/tests.py
@@ -0,0 +1,16 @@
+"""
+This file demonstrates writing tests using the unittest module. These will pass
+when you run "manage.py test".
+
+Replace this with more appropriate tests for your application.
+"""
+
+from django.test import TestCase
+
+
+class SimpleTest(TestCase):
+    def test_basic_addition(self):
+        """
+        Tests that 1 + 1 always equals 2.
+        """
+        self.assertEqual(1 + 1, 2)
diff --git a/circle/storage/views.py b/circle/storage/views.py
new file mode 100644
index 0000000..60f00ef
--- /dev/null
+++ b/circle/storage/views.py
@@ -0,0 +1 @@
+# Create your views here.
diff --git a/circle/vm/__init__.py b/circle/vm/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/circle/vm/__init__.py
diff --git a/circle/vm/models.py b/circle/vm/models.py
new file mode 100755
index 0000000..63b2407
--- /dev/null
+++ b/circle/vm/models.py
@@ -0,0 +1,499 @@
+#!/usr/bin/env python
+
+from datetime import timedelta
+import logging
+
+from . import tasks
+
+# from django.conf.settings import CLOUD_URL
+from django.contrib.auth.models import User
+# from django.core import signing
+from django.db import models
+from django.db.models.signals import pre_delete
+from django.dispatch import receiver
+# from django.template.defaultfilters import escape
+from django.utils import timezone
+from django.utils.translation import ugettext_lazy as _
+
+from model_utils.models import TimeStampedModel
+
+from firewall.models import Vlan, Host
+from storage.models import Disk
+
+logger = logging.getLogger(__name__)
+pwgen = User.objects.make_random_password
+# TODO get this from config
+ACCESS_PROTOCOLS = {
+    # format: id: (name, port, protocol)
+    'rdp': ('rdp', 3389, 'tcp'),
+    'nx': ('nx', 22, 'tcp'),
+    'ssh': ('ssh', 22, 'tcp'),
+}
+ACCESS_METHODS = [(k, ap[0]) for k, ap in ACCESS_PROTOCOLS.iteritems()]
+
+
+class BaseResourceConfigModel(models.Model):
+
+    """Abstract base class for models with base resource configuration
+       parameters.
+    """
+    num_cores = models.IntegerField(help_text=_('Number of CPU cores.'))
+    ram_size = models.IntegerField(help_text=_('Mebibytes of memory.'))
+    max_ram_size = models.IntegerField(help_text=_('Upper memory size limit '
+                                                   'for balloning.'))
+    arch = models.CharField(max_length=10, verbose_name=_('architecture'))
+    priority = models.IntegerField(help_text=_('instance priority'))
+    boot_menu = models.BooleanField()
+    raw_data = models.TextField()
+
+    class Meta:
+        abstract = True
+
+
+class NamedBaseResourceConfig(BaseResourceConfigModel, TimeStampedModel):
+
+    """Pre-created, named base resource configurations.
+    """
+    name = models.CharField(max_length=50, unique=True,
+                            verbose_name=_('name'))
+
+    def __unicode__(self):
+        return self.name
+
+
+class Node(TimeStampedModel):
+    name = models.CharField(max_length=50, unique=True,
+                            verbose_name=_('name'))
+    num_cores = models.IntegerField(help_text=_('Number of CPU cores.'))
+    ram_size = models.IntegerField(help_text=_('Mebibytes of memory.'))
+    priority = models.IntegerField(help_text=_('node usage priority'))
+    host = models.ForeignKey(Host)
+    enabled = models.BooleanField(default=False,
+                                  help_text=_('Indicates whether the node can '
+                                              'be used for hosting.'))
+
+    class Meta:
+        permissions = ()
+
+    @property
+    def online(self):
+        """Indicates whether the node is connected and functional.
+        """
+        pass  # TODO implement check
+
+
+class Lease(models.Model):
+
+    """Lease times for VM instances.
+
+    Specifies a time duration until suspension and deletion of a VM
+    instance.
+    """
+    name = models.CharField(max_length=100, unique=True,
+                            verbose_name=_('name'))
+    suspend_interval_seconds = models.IntegerField()
+    delete_interval_seconds = models.IntegerField()
+
+    @property
+    def suspend_interval(self):
+        return timedelta(seconds=self.suspend_interval_seconds)
+
+    @suspend_interval.setter
+    def suspend_interval(self, value):
+        self.suspend_interval_seconds = value.seconds
+
+    @property
+    def delete_interval(self):
+        return timedelta(seconds=self.delete_interval_seconds)
+
+    @delete_interval.setter
+    def delete_interval(self, value):
+        self.delete_interval_seconds = value.seconds
+
+
+class InstanceTemplate(BaseResourceConfigModel, TimeStampedModel):
+
+    """Virtual machine template.
+
+    Every template has:
+      * a name and a description
+      * an optional parent template
+      * state of the template
+      * an OS name/description
+      * a method of access to the system
+      * default values of base resource configuration
+      * list of attached images
+      * set of interfaces
+      * lease times (suspension & deletion)
+      * time of creation and last modification
+      * ownership information
+    """
+    STATES = [('NEW', _('new')),  # template has just been created
+              ('SAVING', _('saving')),  # changes are being saved
+              ('READY', _('ready'))]  # template is ready for instantiation
+    name = models.CharField(max_length=100, unique=True,
+                            verbose_name=_('name'))
+    description = models.TextField(verbose_name=_('description'),
+                                   blank=True)
+    parent = models.ForeignKey('self', null=True, blank=True,
+                               verbose_name=_('parent template'))
+    system = models.TextField(verbose_name=_('operating system'),
+                              blank=True,
+                              help_text=(_('Name of operating system in '
+                                           'format like "%s".') %
+                                         'Ubuntu 12.04 LTS Desktop amd64'))
+    access_method = models.CharField(max_length=10, choices=ACCESS_METHODS,
+                                     verbose_name=_('access method'))
+    state = models.CharField(max_length=10, choices=STATES,
+                             default='NEW')
+    disks = models.ManyToManyField(Disk, verbose_name=_('disks'),
+                                   related_name='template_set')
+    lease = models.ForeignKey(Lease, related_name='template_set')
+
+    class Meta:
+        ordering = ['name', ]
+        permissions = ()
+        verbose_name = _('template')
+        verbose_name_plural = _('templates')
+
+    def __unicode__(self):
+        return self.name
+
+    def running_instances(self):
+        """Returns the number of running instances of the template.
+        """
+        return self.instance_set.filter(state='RUNNING').count()
+
+    @property
+    def os_type(self):
+        """Get the type of the template's operating system.
+        """
+        if self.access_method == 'rdp':
+            return "win"
+        else:
+            return "linux"
+
+
+class InterfaceTemplate(models.Model):
+
+    """Network interface template for an instance template.
+
+    If the interface is managed, a host will be created for it.
+    """
+    vlan = models.ForeignKey(Vlan)
+    managed = models.BooleanField(default=True)
+    template = models.ForeignKey(InstanceTemplate,
+                                 related_name='interface_set')
+
+    class Meta:
+        permissions = ()
+        verbose_name = _('interface template')
+        verbose_name_plural = _('interface templates')
+
+
+class Instance(BaseResourceConfigModel, TimeStampedModel):
+
+    """Virtual machine instance.
+
+    Every instance has:
+      * a name and a description
+      * an optional parent template
+      * associated share
+      * a generated password for login authentication
+      * time of deletion and time of suspension
+      * lease times (suspension & deletion)
+      * last boot timestamp
+      * host node
+      * current state (libvirt domain state) and operation (Celery job UUID)
+      * time of creation and last modification
+      * base resource configuration values
+      * ownership information
+    """
+    STATES = [('NOSTATE', _('nostate')),
+              ('RUNNING', _('running')),
+              ('BLOCKED', _('blocked')),
+              ('PAUSED', _('paused')),
+              ('SHUTDOWN', _('shutdown')),
+              ('SHUTOFF', _('shutoff')),
+              ('CRASHED', _('crashed')),
+              ('PMSUSPENDED', _('pmsuspended'))]  # libvirt domain states
+    name = models.CharField(blank=True, max_length=100, verbose_name=_('name'))
+    description = models.TextField(blank=True, verbose_name=_('description'))
+    template = models.ForeignKey(InstanceTemplate, blank=True, null=True,
+                                 related_name='instance_set',
+                                 verbose_name=_('template'))
+    pw = models.CharField(help_text=_('Original password of instance'),
+                          max_length=20, verbose_name=_('password'))
+    time_of_suspend = models.DateTimeField(blank=True, default=None, null=True,
+                                           verbose_name=_('time of suspend'))
+    time_of_delete = models.DateTimeField(blank=True, default=None, null=True,
+                                          verbose_name=_('time of delete'))
+    active_since = models.DateTimeField(blank=True, null=True,
+                                        help_text=_('Time stamp of successful '
+                                                    'boot report.'),
+                                        verbose_name=_('active since'))
+    node = models.ForeignKey(Node, blank=True, null=True,
+                             related_name='instance_set',
+                             verbose_name=_('host nose'))
+    state = models.CharField(choices=STATES, default='NOSTATE', max_length=20)
+    operation = models.CharField(blank=True, max_length=100, null=True,
+                                 verbose_name=_('operation'))
+    disks = models.ManyToManyField(Disk, related_name='instance_set',
+                                   verbose_name=_('disks'))
+    lease = models.ForeignKey(Lease)
+    access_method = models.CharField(max_length=10, choices=ACCESS_METHODS,
+                                     verbose_name=_('access method'))
+    owner = models.ForeignKey(User)
+
+    class Meta:
+        ordering = ['pk', ]
+        permissions = ()
+        verbose_name = _('instance')
+        verbose_name_plural = _('instances')
+
+    def __unicode__(self):
+        return self.name
+
+    @classmethod
+    def create_from_template(cls, template, **kwargs):
+        """Create a new instance based on an InstanceTemplate.
+
+        Can also specify parameters as keyword arguments which should override
+        template settings.
+        """
+        # prepare parameters
+        kwargs['template'] = template
+        kwargs.setdefault('name', template.name)
+        kwargs.setdefault('description', template.description)
+        kwargs.setdefault('pw', pwgen())
+        kwargs.setdefault('num_cores', template.num_cores)
+        kwargs.setdefault('ram_size', template.ram_size)
+        kwargs.setdefault('max_ram_size', template.max_ram_size)
+        kwargs.setdefault('arch', template.arch)
+        kwargs.setdefault('priority', template.priority)
+        kwargs.setdefault('lease', template.lease)
+        kwargs.setdefault('access_method', template.access_method)
+        # create instance and do additional setup
+        inst = cls(**kwargs)
+        for disk in template.disks:
+            inst.disks.add(disk.get_exclusive())
+        # save instance
+        inst.save()
+        # create related entities
+        for iftmpl in template.interface_set.all():
+            i = Interface.create_from_template(instance=inst, template=iftmpl)
+            if i.host:
+                i.host.enable_net()
+                port, proto = ACCESS_PROTOCOLS[i.access_method][1:3]
+                i.host.add_port(proto, i.get_port(), port)
+
+        return inst
+
+    # TODO is this obsolete?
+    @models.permalink
+    def get_absolute_url(self):
+        return ('one.views.vm_show', None, {'iid': self.id})
+
+    @property
+    def primary_host(self):
+        interfaces = self.interface_set.select_related('host')
+        hosts = [i.host for i in interfaces if i.host]
+        if not hosts:
+            return None
+        hs = [h for h in hosts if h.ipv6]
+        if hs:
+            return hs[0]
+        hs = [h for h in hosts if not h.shared_ip]
+        if hs:
+            return hs[0]
+        return hosts[0]
+
+    @property
+    def ipv4(self):
+        """Primary IPv4 address of the instance."""
+        return self.primary_host.ipv4 if self.primary_host else None
+
+    @property
+    def ipv6(self):
+        """Primary IPv6 address of the instance."""
+        return self.primary_host.ipv6 if self.primary_host else None
+
+    @property
+    def mac(self):
+        """Primary MAC address of the instance."""
+        return self.primary_host.mac if self.primary_host else None
+
+    @property
+    def uptime(self):
+        """Uptime of the instance.
+        """
+        if self.active_since:
+            return timezone.now() - self.active_since
+        else:
+            return timedelta()  # zero
+
+    def get_age(self):
+        """Deprecated. Use uptime instead.
+
+        Get age of VM in seconds.
+        """
+        return self.uptime.seconds
+
+    @property
+    def waiting(self):
+        """Indicates whether the instance's waiting for an operation to finish.
+        """
+        return self.operation is not None
+
+    def get_connect_port(self, use_ipv6=False):
+        """Get public port number for default access method.
+        """
+        port, proto = ACCESS_PROTOCOLS[self.access_method][1:3]
+        if self.primary_host:
+            endpoints = self.primary_host.get_public_endpoints(port, proto)
+            endpoint = endpoints['ipv6'] if use_ipv6 else endpoints['ipv4']
+            return endpoint[1] if endpoint else None
+        else:
+            return None
+
+    def get_connect_host(self, use_ipv6=False):
+        """Get public hostname.
+        """
+        if not self.firewall_host:
+            return _('None')
+        proto = 'ipv6' if use_ipv6 else 'ipv4'
+        return self.firewall_host.get_hostname(proto=proto)
+
+    def get_connect_uri(self, use_ipv6=False):
+        """Get access parameters in URI format.
+        """
+        try:
+            port = self.get_connect_port(use_ipv6=use_ipv6)
+            host = self.get_connect_host(use_ipv6=use_ipv6)
+            proto = self.access_method
+            if proto == 'ssh':
+                proto = 'sshterm'
+            return ("%(proto)s:cloud:%(pw)s:%(host)s:%(port)d" %
+                    {"port": port, "proto": proto, "pw": self.pw,
+                     "host": host})
+        except:
+            return
+
+    def deploy(self):
+        ''' Launch celery task to handle asyncron jobs.
+        '''
+        manager.deploy.apply_async(self)
+
+    def deploy_task(self):
+        ''' Deploy virtual machine on remote node
+        '''
+        instance = {
+            'name': 'cloud-' + self.id,
+            'vcpu': self.num_cores,
+            'memory': self.ram_size,
+            'memory_max': self.max_ram_size,
+            'cpu_share': self.priority,
+            'arch': self.arch,
+            'boot_menu': self.boot_menu,
+            'network_list': [n.get_vmnetwork_desc()
+                             for n in self.interface_set.all()],
+            'disk_list': [n.get_vmdisk_desc() for n in self.disks.all()],
+            'graphics': {'type': 'vnc',
+                    'listen': '0.0.0.0',
+                    'passwd': '',
+                    'port': self.get_vnc_port()},
+            'raw_data': self.raw_data
+        }
+        tasks.create.apply_async(instance, queue=self.node + ".vm").get()
+
+    def stop(self):
+        # TODO implement
+        pass
+
+    def resume(self):
+        # TODO implement
+        pass
+
+    def poweroff(self):
+        # TODO implement
+        pass
+
+    def restart(self):
+        # TODO implement
+        pass
+
+    def renew(self, which='both'):
+        """Renew virtual machine instance leases.
+        """
+        if which not in ['suspend', 'delete', 'both']:
+            raise ValueError('No such expiration type.')
+        if which in ['suspend', 'both']:
+            self.time_of_suspend = timezone.now() + self.lease.suspend_interval
+        if which in ['delete', 'both']:
+            self.time_of_delete = timezone.now() + self.lease.delete_interval
+        self.save()
+
+    def save_as(self):
+        """Save image and shut down."""
+        imgname = "template-%d-%d" % (self.template.id, self.id)
+        from .tasks import SaveAsTask
+        SaveAsTask.delay(one_id=self.one_id, new_img=imgname)
+        self._change_state("SHUTDOWN")
+        self.save()
+        t = self.template
+        t.state = 'SAVING'
+        t.save()
+
+    def check_if_is_save_as_done(self):
+        if self.state != 'DONE':
+            return False
+        Disk.update(delete=False)
+        imgname = "template-%d-%d" % (self.template.id, self.id)
+        disks = Disk.objects.filter(name=imgname)
+        if len(disks) != 1:
+            return False
+        self.template.disk_id = disks[0].id
+        self.template.state = 'READY'
+        self.template.save()
+        self.firewall_host_delete()
+        return True
+
+
+@receiver(pre_delete, sender=Instance, dispatch_uid="delete_instance_pre")
+def delete_instance_pre(sender, instance, using, **kwargs):
+    # TODO implement
+    pass
+
+
+class Interface(models.Model):
+
+    """Network interface for an instance.
+    """
+    vlan = models.ForeignKey(Vlan, related_name="vm_interface")
+    host = models.ForeignKey(Host, blank=True, null=True)
+    instance = models.ForeignKey(Instance, related_name='interface_set')
+
+    def mac_generator(self):
+        # MAC 02:XX:XX:X:VID
+        pass
+
+    def get_vmnetwork_desc(self):
+        return {
+            'name': 'cloud-' + self.instance.id + '-' + self.vlan.vid,
+            'bridge': 'cloud',
+            'mac': self.mac_generator(),
+            'ipv4': self.host.ipv4 if self.host is not None else None,
+            'ipv6': self.host.ipv6 if self.host is not None else None,
+            'vlan': self.vlan.vid,
+            'managed': self.host is not None
+        }
+
+    @classmethod
+    def create_from_template(cls, instance, template):
+        """Create a new interface for an instance based on an
+           InterfaceTemplate.
+        """
+        host = Host(vlan=template.vlan) if template.managed else None
+        iface = cls(vlan=template.vlan, host=host, instance=instance)
+        iface.save()
+        return iface
diff --git a/circle/vm/tasks.py b/circle/vm/tasks.py
new file mode 100644
index 0000000..111aacf
--- /dev/null
+++ b/circle/vm/tasks.py
@@ -0,0 +1,6 @@
+from manager.manager import celery
+
+
+@celery.task(name='vmdriver.create')
+def create(parameters):
+    pass
diff --git a/circle/vm/tests/__init__.py b/circle/vm/tests/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/circle/vm/tests/__init__.py
diff --git a/circle/vm/tests/test_models.py b/circle/vm/tests/test_models.py
new file mode 100644
index 0000000..ca14d68
--- /dev/null
+++ b/circle/vm/tests/test_models.py
@@ -0,0 +1,8 @@
+from django.test import TestCase
+from .models import Template
+
+
+class TemplateTestCase(TestCase):
+    def test_template_creation(self):
+        template = Template(name='My first template',
+                            access_method='ssh', )  # TODO add images & net
diff --git a/circle/vm/views.py b/circle/vm/views.py
new file mode 100644
index 0000000..60f00ef
--- /dev/null
+++ b/circle/vm/views.py
@@ -0,0 +1 @@
+# Create your views here.