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