from __future__ import unicode_literals
import django_tables2 as tables
from django_tables2.utils import Accessor
from dcim.models import Interface
from tenancy.tables import COL_TENANT
from utilities.tables import BaseTable, BooleanColumn, ToggleColumn
from .models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF
RIR_UTILIZATION = """
{% if record.stats.total %}
{{ record.stats.percentages.active }}%
{{ record.stats.percentages.reserved }}%
{{ record.stats.percentages.deprecated }}%
{{ record.stats.percentages.available }}%
{% endif %}
"""
RIR_ACTIONS = """
{% if perms.ipam.change_rir %}
{% endif %}
"""
UTILIZATION_GRAPH = """
{% load helpers %}
{% if record.pk %}{% utilization_graph record.get_utilization %}{% else %}—{% endif %}
"""
ROLE_PREFIX_COUNT = """
{{ value }}
"""
ROLE_VLAN_COUNT = """
{{ value }}
"""
ROLE_ACTIONS = """
{% if perms.ipam.change_role %}
{% endif %}
"""
PREFIX_LINK = """
{% if record.has_children %}
{% else %}
{% endif %}
{{ record.prefix }}
"""
PREFIX_ROLE_LINK = """
{% if record.role %}
{{ record.role }}
{% else %}
—
{% endif %}
"""
IPADDRESS_LINK = """
{% if record.pk %}
{{ record.address }}
{% elif perms.ipam.add_ipaddress %}
{% if record.0 <= 65536 %}{{ record.0 }}{% else %}Many{% endif %} IP{{ record.0|pluralize }} available
{% else %}
{% if record.0 <= 65536 %}{{ record.0 }}{% else %}Many{% endif %} IP{{ record.0|pluralize }} available
{% endif %}
"""
IPADDRESS_ASSIGN_LINK = """
{{ record }}
"""
IPADDRESS_PARENT = """
{% if record.interface %}
{{ record.interface.parent }}
{% else %}
—
{% endif %}
"""
VRF_LINK = """
{% if record.vrf %}
{{ record.vrf }}
{% elif prefix.vrf %}
{{ prefix.vrf }}
{% else %}
Global
{% endif %}
"""
STATUS_LABEL = """
{% if record.pk %}
{{ record.get_status_display }}
{% else %}
Available
{% endif %}
"""
VLAN_LINK = """
{% if record.pk %}
{{ record.vid }}
{% elif perms.ipam.add_vlan %}
{{ record.available }} VLAN{{ record.available|pluralize }} available
{% else %}
{{ record.available }} VLAN{{ record.available|pluralize }} available
{% endif %}
"""
VLAN_PREFIXES = """
{% for prefix in record.prefixes.all %}
{{ prefix }}{% if not forloop.last %}
{% endif %}
{% empty %}
—
{% endfor %}
"""
VLAN_ROLE_LINK = """
{% if record.role %}
{{ record.role }}
{% else %}
—
{% endif %}
"""
VLANGROUP_ACTIONS = """
{% with next_vid=record.get_next_available_vid %}
{% if next_vid and perms.ipam.add_vlan %}
{% endif %}
{% endwith %}
{% if perms.ipam.change_vlangroup %}
{% endif %}
"""
VLAN_MEMBER_UNTAGGED = """
{% if record.untagged_vlan_id == vlan.pk %}
{% endif %}
"""
VLAN_MEMBER_ACTIONS = """
{% if perms.dcim.change_interface %}
{% endif %}
"""
TENANT_LINK = """
{% if record.tenant %}
{{ record.tenant }}
{% elif record.vrf.tenant %}
{{ record.vrf.tenant }}*
{% else %}
—
{% endif %}
"""
#
# VRFs
#
class VRFTable(BaseTable):
pk = ToggleColumn()
name = tables.LinkColumn()
rd = tables.Column(verbose_name='RD')
tenant = tables.TemplateColumn(template_code=COL_TENANT)
class Meta(BaseTable.Meta):
model = VRF
fields = ('pk', 'name', 'rd', 'tenant', 'description')
#
# RIRs
#
class RIRTable(BaseTable):
pk = ToggleColumn()
name = tables.LinkColumn(verbose_name='Name')
is_private = BooleanColumn(verbose_name='Private')
aggregate_count = tables.Column(verbose_name='Aggregates')
actions = tables.TemplateColumn(template_code=RIR_ACTIONS, attrs={'td': {'class': 'text-right'}}, verbose_name='')
class Meta(BaseTable.Meta):
model = RIR
fields = ('pk', 'name', 'is_private', 'aggregate_count', 'actions')
class RIRDetailTable(RIRTable):
stats_total = tables.Column(
accessor='stats.total',
verbose_name='Total',
footer=lambda table: sum(r.stats['total'] for r in table.data)
)
stats_active = tables.Column(
accessor='stats.active',
verbose_name='Active',
footer=lambda table: sum(r.stats['active'] for r in table.data)
)
stats_reserved = tables.Column(
accessor='stats.reserved',
verbose_name='Reserved',
footer=lambda table: sum(r.stats['reserved'] for r in table.data)
)
stats_deprecated = tables.Column(
accessor='stats.deprecated',
verbose_name='Deprecated',
footer=lambda table: sum(r.stats['deprecated'] for r in table.data)
)
stats_available = tables.Column(
accessor='stats.available',
verbose_name='Available',
footer=lambda table: sum(r.stats['available'] for r in table.data)
)
utilization = tables.TemplateColumn(
template_code=RIR_UTILIZATION,
verbose_name='Utilization'
)
class Meta(RIRTable.Meta):
fields = (
'pk', 'name', 'is_private', 'aggregate_count', 'stats_total', 'stats_active', 'stats_reserved',
'stats_deprecated', 'stats_available', 'utilization', 'actions',
)
#
# Aggregates
#
class AggregateTable(BaseTable):
pk = ToggleColumn()
prefix = tables.LinkColumn(verbose_name='Aggregate')
date_added = tables.DateColumn(format="Y-m-d", verbose_name='Added')
class Meta(BaseTable.Meta):
model = Aggregate
fields = ('pk', 'prefix', 'rir', 'date_added', 'description')
class AggregateDetailTable(AggregateTable):
child_count = tables.Column(verbose_name='Prefixes')
utilization = tables.TemplateColumn(UTILIZATION_GRAPH, orderable=False, verbose_name='Utilization')
class Meta(AggregateTable.Meta):
fields = ('pk', 'prefix', 'rir', 'child_count', 'utilization', 'date_added', 'description')
#
# Roles
#
class RoleTable(BaseTable):
pk = ToggleColumn()
prefix_count = tables.TemplateColumn(
accessor=Accessor('prefixes.count'),
template_code=ROLE_PREFIX_COUNT,
orderable=False,
verbose_name='Prefixes'
)
vlan_count = tables.TemplateColumn(
accessor=Accessor('vlans.count'),
template_code=ROLE_VLAN_COUNT,
orderable=False,
verbose_name='VLANs'
)
actions = tables.TemplateColumn(template_code=ROLE_ACTIONS, attrs={'td': {'class': 'text-right'}}, verbose_name='')
class Meta(BaseTable.Meta):
model = Role
fields = ('pk', 'name', 'prefix_count', 'vlan_count', 'slug', 'actions')
#
# Prefixes
#
class PrefixTable(BaseTable):
pk = ToggleColumn()
prefix = tables.TemplateColumn(PREFIX_LINK, attrs={'th': {'style': 'padding-left: 17px'}})
status = tables.TemplateColumn(STATUS_LABEL)
vrf = tables.TemplateColumn(VRF_LINK, verbose_name='VRF')
tenant = tables.TemplateColumn(template_code=TENANT_LINK)
site = tables.LinkColumn('dcim:site', args=[Accessor('site.slug')])
vlan = tables.LinkColumn('ipam:vlan', args=[Accessor('vlan.pk')], verbose_name='VLAN')
role = tables.TemplateColumn(PREFIX_ROLE_LINK)
class Meta(BaseTable.Meta):
model = Prefix
fields = ('pk', 'prefix', 'status', 'vrf', 'tenant', 'site', 'vlan', 'role', 'description')
row_attrs = {
'class': lambda record: 'success' if not record.pk else '',
}
class PrefixDetailTable(PrefixTable):
utilization = tables.TemplateColumn(UTILIZATION_GRAPH, orderable=False)
class Meta(PrefixTable.Meta):
fields = ('pk', 'prefix', 'status', 'vrf', 'utilization', 'tenant', 'site', 'vlan', 'role', 'description')
#
# IPAddresses
#
class IPAddressTable(BaseTable):
pk = ToggleColumn()
address = tables.TemplateColumn(IPADDRESS_LINK, verbose_name='IP Address')
vrf = tables.TemplateColumn(VRF_LINK, verbose_name='VRF')
status = tables.TemplateColumn(STATUS_LABEL)
tenant = tables.TemplateColumn(template_code=TENANT_LINK)
parent = tables.TemplateColumn(IPADDRESS_PARENT, orderable=False)
interface = tables.Column(orderable=False)
class Meta(BaseTable.Meta):
model = IPAddress
fields = ('pk', 'address', 'vrf', 'status', 'role', 'tenant', 'parent', 'interface', 'description')
row_attrs = {
'class': lambda record: 'success' if not isinstance(record, IPAddress) else '',
}
class IPAddressDetailTable(IPAddressTable):
nat_inside = tables.LinkColumn(
'ipam:ipaddress', args=[Accessor('nat_inside.pk')], orderable=False, verbose_name='NAT (Inside)'
)
class Meta(IPAddressTable.Meta):
fields = (
'pk', 'address', 'vrf', 'status', 'role', 'tenant', 'nat_inside', 'parent', 'interface', 'description',
)
class IPAddressAssignTable(BaseTable):
address = tables.TemplateColumn(IPADDRESS_ASSIGN_LINK, verbose_name='IP Address')
status = tables.TemplateColumn(STATUS_LABEL)
parent = tables.TemplateColumn(IPADDRESS_PARENT, orderable=False)
interface = tables.Column(orderable=False)
class Meta(BaseTable.Meta):
model = IPAddress
fields = ('address', 'vrf', 'status', 'role', 'tenant', 'parent', 'interface', 'description')
orderable = False
class InterfaceIPAddressTable(BaseTable):
"""
List IP addresses assigned to a specific Interface.
"""
address = tables.TemplateColumn(IPADDRESS_ASSIGN_LINK, verbose_name='IP Address')
vrf = tables.TemplateColumn(VRF_LINK, verbose_name='VRF')
status = tables.TemplateColumn(STATUS_LABEL)
tenant = tables.TemplateColumn(template_code=TENANT_LINK)
class Meta(BaseTable.Meta):
model = IPAddress
fields = ('address', 'vrf', 'status', 'role', 'tenant', 'description')
#
# VLAN groups
#
class VLANGroupTable(BaseTable):
pk = ToggleColumn()
name = tables.LinkColumn(verbose_name='Name')
site = tables.LinkColumn('dcim:site', args=[Accessor('site.slug')], verbose_name='Site')
vlan_count = tables.Column(verbose_name='VLANs')
slug = tables.Column(verbose_name='Slug')
actions = tables.TemplateColumn(template_code=VLANGROUP_ACTIONS, attrs={'td': {'class': 'text-right'}},
verbose_name='')
class Meta(BaseTable.Meta):
model = VLANGroup
fields = ('pk', 'name', 'site', 'vlan_count', 'slug', 'actions')
#
# VLANs
#
class VLANTable(BaseTable):
pk = ToggleColumn()
vid = tables.TemplateColumn(VLAN_LINK, verbose_name='ID')
site = tables.LinkColumn('dcim:site', args=[Accessor('site.slug')])
group = tables.LinkColumn('ipam:vlangroup_vlans', args=[Accessor('group.pk')], verbose_name='Group')
tenant = tables.TemplateColumn(template_code=COL_TENANT)
status = tables.TemplateColumn(STATUS_LABEL)
role = tables.TemplateColumn(VLAN_ROLE_LINK)
class Meta(BaseTable.Meta):
model = VLAN
fields = ('pk', 'vid', 'site', 'group', 'name', 'tenant', 'status', 'role', 'description')
row_attrs = {
'class': lambda record: 'success' if not isinstance(record, VLAN) else '',
}
class VLANDetailTable(VLANTable):
prefixes = tables.TemplateColumn(VLAN_PREFIXES, orderable=False, verbose_name='Prefixes')
class Meta(VLANTable.Meta):
fields = ('pk', 'vid', 'site', 'group', 'name', 'prefixes', 'tenant', 'status', 'role', 'description')
class VLANMemberTable(BaseTable):
parent = tables.LinkColumn(order_by=['device', 'virtual_machine'])
name = tables.Column(verbose_name='Interface')
untagged = tables.TemplateColumn(
template_code=VLAN_MEMBER_UNTAGGED,
orderable=False
)
actions = tables.TemplateColumn(
template_code=VLAN_MEMBER_ACTIONS,
attrs={'td': {'class': 'text-right'}},
verbose_name=''
)
class Meta(BaseTable.Meta):
model = Interface
fields = ('parent', 'name', 'untagged', 'actions')
class InterfaceVLANTable(BaseTable):
"""
List VLANs assigned to a specific Interface.
"""
vid = tables.LinkColumn('ipam:vlan', args=[Accessor('pk')], verbose_name='ID')
tagged = BooleanColumn()
site = tables.LinkColumn('dcim:site', args=[Accessor('site.slug')])
group = tables.Column(accessor=Accessor('group.name'), verbose_name='Group')
tenant = tables.TemplateColumn(template_code=COL_TENANT)
status = tables.TemplateColumn(STATUS_LABEL)
role = tables.TemplateColumn(VLAN_ROLE_LINK)
class Meta(BaseTable.Meta):
model = VLAN
fields = ('vid', 'tagged', 'site', 'group', 'name', 'tenant', 'status', 'role', 'description')
def __init__(self, interface, *args, **kwargs):
self.interface = interface
super(InterfaceVLANTable, self).__init__(*args, **kwargs)
#
# Services
#
class ServiceTable(BaseTable):
pk = ToggleColumn()
name = tables.LinkColumn(
viewname='ipam:service',
args=[Accessor('pk')]
)
class Meta(BaseTable.Meta):
model = Service
fields = ('pk', 'name', 'parent', 'protocol', 'port', 'description')