1import django_tables2 as tables
2from django.utils.safestring import mark_safe
3from django_tables2.utils import Accessor
4
5from dcim.models import Interface
6from tenancy.tables import TenantColumn
7from utilities.tables import (
8    BaseTable, BooleanColumn, ButtonsColumn, ChoiceFieldColumn, ContentTypeColumn, LinkedCountColumn, TagColumn,
9    TemplateColumn, ToggleColumn,
10)
11from virtualization.models import VMInterface
12from ipam.models import *
13
14__all__ = (
15    'InterfaceVLANTable',
16    'VLANDevicesTable',
17    'VLANGroupTable',
18    'VLANMembersTable',
19    'VLANTable',
20    'VLANVirtualMachinesTable',
21)
22
23AVAILABLE_LABEL = mark_safe('<span class="badge bg-success">Available</span>')
24
25VLAN_LINK = """
26{% if record.pk %}
27    <a href="{{ record.get_absolute_url }}">{{ record.vid }}</a>
28{% elif perms.ipam.add_vlan %}
29    <a href="{% url 'ipam:vlan_add' %}?vid={{ record.vid }}{% if record.vlan_group %}&group={{ record.vlan_group.pk }}{% endif %}" class="btn btn-sm btn-success">{{ record.available }} VLAN{{ record.available|pluralize }} available</a>
30{% else %}
31    {{ record.available }} VLAN{{ record.available|pluralize }} available
32{% endif %}
33"""
34
35VLAN_PREFIXES = """
36{% for prefix in record.prefixes.all %}
37    <a href="{% url 'ipam:prefix' pk=prefix.pk %}">{{ prefix }}</a>{% if not forloop.last %}<br />{% endif %}
38{% endfor %}
39"""
40
41VLANGROUP_ADD_VLAN = """
42{% with next_vid=record.get_next_available_vid %}
43    {% if next_vid and perms.ipam.add_vlan %}
44        <a href="{% url 'ipam:vlan_add' %}?group={{ record.pk }}&vid={{ next_vid }}" title="Add VLAN" class="btn btn-sm btn-success">
45            <i class="mdi mdi-plus-thick" aria-hidden="true"></i>
46        </a>
47    {% endif %}
48{% endwith %}
49"""
50
51VLAN_MEMBER_TAGGED = """
52{% if record.untagged_vlan_id == object.pk %}
53    <span class="text-danger"><i class="mdi mdi-close-thick"></i></span>
54{% else %}
55    <span class="text-success"><i class="mdi mdi-check-bold"></i></span>
56{% endif %}
57"""
58
59
60#
61# VLAN groups
62#
63
64class VLANGroupTable(BaseTable):
65    pk = ToggleColumn()
66    name = tables.Column(linkify=True)
67    scope_type = ContentTypeColumn()
68    scope = tables.Column(
69        linkify=True,
70        orderable=False
71    )
72    vlan_count = LinkedCountColumn(
73        viewname='ipam:vlan_list',
74        url_params={'group_id': 'pk'},
75        verbose_name='VLANs'
76    )
77    actions = ButtonsColumn(
78        model=VLANGroup,
79        prepend_template=VLANGROUP_ADD_VLAN
80    )
81
82    class Meta(BaseTable.Meta):
83        model = VLANGroup
84        fields = ('pk', 'id', 'name', 'scope_type', 'scope', 'vlan_count', 'slug', 'description', 'actions')
85        default_columns = ('pk', 'name', 'scope_type', 'scope', 'vlan_count', 'description', 'actions')
86
87
88#
89# VLANs
90#
91
92class VLANTable(BaseTable):
93    pk = ToggleColumn()
94    vid = tables.TemplateColumn(
95        template_code=VLAN_LINK,
96        verbose_name='VID'
97    )
98    name = tables.Column(
99        linkify=True
100    )
101    site = tables.Column(
102        linkify=True
103    )
104    group = tables.Column(
105        linkify=True
106    )
107    tenant = TenantColumn()
108    status = ChoiceFieldColumn(
109        default=AVAILABLE_LABEL
110    )
111    role = tables.Column(
112        linkify=True
113    )
114    prefixes = TemplateColumn(
115        template_code=VLAN_PREFIXES,
116        orderable=False,
117        verbose_name='Prefixes'
118    )
119    tags = TagColumn(
120        url_name='ipam:vlan_list'
121    )
122
123    class Meta(BaseTable.Meta):
124        model = VLAN
125        fields = ('pk', 'id', 'vid', 'name', 'site', 'group', 'prefixes', 'tenant', 'status', 'role', 'description', 'tags')
126        default_columns = ('pk', 'vid', 'name', 'site', 'group', 'prefixes', 'tenant', 'status', 'role', 'description')
127        row_attrs = {
128            'class': lambda record: 'success' if not isinstance(record, VLAN) else '',
129        }
130
131
132class VLANMembersTable(BaseTable):
133    """
134    Base table for Interface and VMInterface assignments
135    """
136    name = tables.Column(
137        linkify=True,
138        verbose_name='Interface'
139    )
140    tagged = tables.TemplateColumn(
141        template_code=VLAN_MEMBER_TAGGED,
142        orderable=False
143    )
144
145
146class VLANDevicesTable(VLANMembersTable):
147    device = tables.Column(
148        linkify=True
149    )
150    actions = ButtonsColumn(Interface, buttons=['edit'])
151
152    class Meta(BaseTable.Meta):
153        model = Interface
154        fields = ('device', 'name', 'tagged', 'actions')
155        exclude = ('id', )
156
157
158class VLANVirtualMachinesTable(VLANMembersTable):
159    virtual_machine = tables.Column(
160        linkify=True
161    )
162    actions = ButtonsColumn(VMInterface, buttons=['edit'])
163
164    class Meta(BaseTable.Meta):
165        model = VMInterface
166        fields = ('virtual_machine', 'name', 'tagged', 'actions')
167        exclude = ('id', )
168
169
170class InterfaceVLANTable(BaseTable):
171    """
172    List VLANs assigned to a specific Interface.
173    """
174    vid = tables.Column(
175        linkify=True,
176        verbose_name='ID'
177    )
178    tagged = BooleanColumn()
179    site = tables.Column(
180        linkify=True
181    )
182    group = tables.Column(
183        accessor=Accessor('group__name'),
184        verbose_name='Group'
185    )
186    tenant = TenantColumn()
187    status = ChoiceFieldColumn()
188    role = tables.Column(
189        linkify=True
190    )
191
192    class Meta(BaseTable.Meta):
193        model = VLAN
194        fields = ('vid', 'tagged', 'site', 'group', 'name', 'tenant', 'status', 'role', 'description')
195        exclude = ('id', )
196
197    def __init__(self, interface, *args, **kwargs):
198        self.interface = interface
199        super().__init__(*args, **kwargs)
200