tables.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. import django_tables2 as tables
  2. from django_tables2.utils import Accessor
  3. from utilities.tables import BaseTable, ToggleColumn
  4. from .models import Aggregate, IPAddress, Prefix, RIR, Role, VLAN, VLANGroup, VRF
  5. RIR_UTILIZATION = """
  6. <div class="progress">
  7. {% if record.stats.total %}
  8. <div class="progress-bar" role="progressbar" style="width: {{ record.stats.percentages.active }}%;">
  9. <span class="sr-only">{{ record.stats.percentages.active }}%</span>
  10. </div>
  11. <div class="progress-bar progress-bar-info" role="progressbar" style="width: {{ record.stats.percentages.reserved }}%;">
  12. <span class="sr-only">{{ record.stats.percentages.reserved }}%</span>
  13. </div>
  14. <div class="progress-bar progress-bar-danger" role="progressbar" style="width: {{ record.stats.percentages.deprecated }}%;">
  15. <span class="sr-only">{{ record.stats.percentages.deprecated }}%</span>
  16. </div>
  17. <div class="progress-bar progress-bar-success" role="progressbar" style="width: {{ record.stats.percentages.available }}%;">
  18. <span class="sr-only">{{ record.stats.percentages.available }}%</span>
  19. </div>
  20. {% endif %}
  21. </div>
  22. """
  23. RIR_ACTIONS = """
  24. {% if perms.ipam.change_rir %}
  25. <a href="{% url 'ipam:rir_edit' slug=record.slug %}" class="btn btn-xs btn-warning"><i class="glyphicon glyphicon-pencil" aria-hidden="true"></i></a>
  26. {% endif %}
  27. """
  28. UTILIZATION_GRAPH = """
  29. {% load helpers %}
  30. {% utilization_graph value %}
  31. """
  32. ROLE_ACTIONS = """
  33. {% if perms.ipam.change_role %}
  34. <a href="{% url 'ipam:role_edit' slug=record.slug %}" class="btn btn-xs btn-warning"><i class="glyphicon glyphicon-pencil" aria-hidden="true"></i></a>
  35. {% endif %}
  36. """
  37. PREFIX_LINK = """
  38. {% if record.has_children %}
  39. <span style="padding-left: {{ record.depth }}0px "><i class="fa fa-caret-right"></i></a>
  40. {% else %}
  41. <span style="padding-left: {{ record.depth }}9px">
  42. {% endif %}
  43. <a href="{% if record.pk %}{% url 'ipam:prefix' pk=record.pk %}{% else %}{% url 'ipam:prefix_add' %}?prefix={{ record }}{% if parent.vrf %}&vrf={{ parent.vrf.pk }}{% endif %}{% if parent.site %}&site={{ parent.site.pk }}{% endif %}{% endif %}">{{ record.prefix }}</a>
  44. </span>
  45. """
  46. PREFIX_LINK_BRIEF = """
  47. <span style="padding-left: {{ record.depth }}0px">
  48. <a href="{% if record.pk %}{% url 'ipam:prefix' pk=record.pk %}{% else %}{% url 'ipam:prefix_add' %}?prefix={{ record }}{% if parent.vrf %}&vrf={{ parent.vrf.pk }}{% endif %}{% if parent.site %}&site={{ parent.site.pk }}{% endif %}{% endif %}">{{ record.prefix }}</a>
  49. </span>
  50. """
  51. IPADDRESS_LINK = """
  52. {% if record.pk %}
  53. <a href="{{ record.get_absolute_url }}">{{ record.address }}</a>
  54. {% elif perms.ipam.add_ipaddress %}
  55. <a href="{% url 'ipam:ipaddress_add' %}?address={{ record.1 }}{% if prefix.vrf %}&vrf={{ prefix.vrf.pk }}{% endif %}" class="btn btn-xs btn-success">{% if record.0 <= 65536 %}{{ record.0 }}{% else %}Lots of{% endif %} free IP{{ record.0|pluralize }}</a>
  56. {% else %}
  57. {{ record.0 }}
  58. {% endif %}
  59. """
  60. VRF_LINK = """
  61. {% if record.vrf %}
  62. <a href="{{ record.vrf.get_absolute_url }}">{{ record.vrf }}</a>
  63. {% elif prefix.vrf %}
  64. {{ prefix.vrf }}
  65. {% else %}
  66. Global
  67. {% endif %}
  68. """
  69. STATUS_LABEL = """
  70. {% if record.pk %}
  71. <span class="label label-{{ record.get_status_class }}">{{ record.get_status_display }}</span>
  72. {% else %}
  73. <span class="label label-success">Available</span>
  74. {% endif %}
  75. """
  76. VLANGROUP_ACTIONS = """
  77. {% if perms.ipam.change_vlangroup %}
  78. <a href="{% url 'ipam:vlangroup_edit' pk=record.pk %}" class="btn btn-xs btn-warning"><i class="glyphicon glyphicon-pencil" aria-hidden="true"></i></a>
  79. {% endif %}
  80. """
  81. TENANT_LINK = """
  82. {% if record.tenant %}
  83. <a href="{% url 'tenancy:tenant' slug=record.tenant.slug %}">{{ record.tenant }}</a>
  84. {% elif record.vrf.tenant %}
  85. <a href="{% url 'tenancy:tenant' slug=record.vrf.tenant.slug %}">{{ record.vrf.tenant }}</a>*
  86. {% else %}
  87. &mdash;
  88. {% endif %}
  89. """
  90. #
  91. # VRFs
  92. #
  93. class VRFTable(BaseTable):
  94. pk = ToggleColumn()
  95. name = tables.LinkColumn('ipam:vrf', args=[Accessor('pk')], verbose_name='Name')
  96. rd = tables.Column(verbose_name='RD')
  97. tenant = tables.LinkColumn('tenancy:tenant', args=[Accessor('tenant.slug')], verbose_name='Tenant')
  98. description = tables.Column(orderable=False, verbose_name='Description')
  99. class Meta(BaseTable.Meta):
  100. model = VRF
  101. fields = ('pk', 'name', 'rd', 'tenant', 'description')
  102. #
  103. # RIRs
  104. #
  105. class RIRTable(BaseTable):
  106. pk = ToggleColumn()
  107. name = tables.LinkColumn(verbose_name='Name')
  108. is_private = tables.BooleanColumn(verbose_name='Private')
  109. aggregate_count = tables.Column(verbose_name='Aggregates')
  110. stats_total = tables.Column(accessor='stats.total', verbose_name='Total',
  111. footer=lambda table: sum(r.stats['total'] for r in table.data))
  112. stats_active = tables.Column(accessor='stats.active', verbose_name='Active',
  113. footer=lambda table: sum(r.stats['active'] for r in table.data))
  114. stats_reserved = tables.Column(accessor='stats.reserved', verbose_name='Reserved',
  115. footer=lambda table: sum(r.stats['reserved'] for r in table.data))
  116. stats_deprecated = tables.Column(accessor='stats.deprecated', verbose_name='Deprecated',
  117. footer=lambda table: sum(r.stats['deprecated'] for r in table.data))
  118. stats_available = tables.Column(accessor='stats.available', verbose_name='Available',
  119. footer=lambda table: sum(r.stats['available'] for r in table.data))
  120. utilization = tables.TemplateColumn(template_code=RIR_UTILIZATION, verbose_name='Utilization')
  121. actions = tables.TemplateColumn(template_code=RIR_ACTIONS, attrs={'td': {'class': 'text-right'}}, verbose_name='')
  122. class Meta(BaseTable.Meta):
  123. model = RIR
  124. fields = ('pk', 'name', 'is_private', 'aggregate_count', 'stats_total', 'stats_active', 'stats_reserved',
  125. 'stats_deprecated', 'stats_available', 'utilization', 'actions')
  126. #
  127. # Aggregates
  128. #
  129. class AggregateTable(BaseTable):
  130. pk = ToggleColumn()
  131. prefix = tables.LinkColumn('ipam:aggregate', args=[Accessor('pk')], verbose_name='Aggregate')
  132. rir = tables.Column(verbose_name='RIR')
  133. child_count = tables.Column(verbose_name='Prefixes')
  134. get_utilization = tables.TemplateColumn(UTILIZATION_GRAPH, orderable=False, verbose_name='Utilization')
  135. date_added = tables.DateColumn(format="Y-m-d", verbose_name='Added')
  136. description = tables.Column(orderable=False, verbose_name='Description')
  137. class Meta(BaseTable.Meta):
  138. model = Aggregate
  139. fields = ('pk', 'prefix', 'rir', 'child_count', 'get_utilization', 'date_added', 'description')
  140. #
  141. # Roles
  142. #
  143. class RoleTable(BaseTable):
  144. pk = ToggleColumn()
  145. name = tables.Column(verbose_name='Name')
  146. prefix_count = tables.Column(accessor=Accessor('count_prefixes'), orderable=False, verbose_name='Prefixes')
  147. vlan_count = tables.Column(accessor=Accessor('count_vlans'), orderable=False, verbose_name='VLANs')
  148. slug = tables.Column(verbose_name='Slug')
  149. actions = tables.TemplateColumn(template_code=ROLE_ACTIONS, attrs={'td': {'class': 'text-right'}}, verbose_name='')
  150. class Meta(BaseTable.Meta):
  151. model = Role
  152. fields = ('pk', 'name', 'prefix_count', 'vlan_count', 'slug', 'actions')
  153. #
  154. # Prefixes
  155. #
  156. class PrefixTable(BaseTable):
  157. pk = ToggleColumn()
  158. status = tables.TemplateColumn(STATUS_LABEL, verbose_name='Status')
  159. prefix = tables.TemplateColumn(PREFIX_LINK, verbose_name='Prefix')
  160. vrf = tables.TemplateColumn(VRF_LINK, verbose_name='VRF')
  161. tenant = tables.TemplateColumn(TENANT_LINK, verbose_name='Tenant')
  162. site = tables.LinkColumn('dcim:site', args=[Accessor('site.slug')], verbose_name='Site')
  163. role = tables.Column(verbose_name='Role')
  164. description = tables.Column(orderable=False, verbose_name='Description')
  165. class Meta(BaseTable.Meta):
  166. model = Prefix
  167. fields = ('pk', 'prefix', 'status', 'vrf', 'tenant', 'site', 'role', 'description')
  168. row_attrs = {
  169. 'class': lambda record: 'success' if not record.pk else '',
  170. }
  171. class PrefixBriefTable(BaseTable):
  172. prefix = tables.TemplateColumn(PREFIX_LINK_BRIEF, verbose_name='Prefix')
  173. vrf = tables.LinkColumn('ipam:vrf', args=[Accessor('vrf.pk')], default='Global', verbose_name='VRF')
  174. site = tables.LinkColumn('dcim:site', args=[Accessor('site.slug')], verbose_name='Site')
  175. status = tables.TemplateColumn(STATUS_LABEL, verbose_name='Status')
  176. role = tables.Column(verbose_name='Role')
  177. class Meta(BaseTable.Meta):
  178. model = Prefix
  179. fields = ('prefix', 'vrf', 'status', 'site', 'role')
  180. orderable = False
  181. #
  182. # IPAddresses
  183. #
  184. class IPAddressTable(BaseTable):
  185. pk = ToggleColumn()
  186. address = tables.TemplateColumn(IPADDRESS_LINK, verbose_name='IP Address')
  187. status = tables.TemplateColumn(STATUS_LABEL, verbose_name='Status')
  188. vrf = tables.TemplateColumn(VRF_LINK, verbose_name='VRF')
  189. tenant = tables.TemplateColumn(TENANT_LINK, verbose_name='Tenant')
  190. device = tables.LinkColumn('dcim:device', args=[Accessor('interface.device.pk')], orderable=False,
  191. verbose_name='Device')
  192. interface = tables.Column(orderable=False, verbose_name='Interface')
  193. description = tables.Column(orderable=False, verbose_name='Description')
  194. class Meta(BaseTable.Meta):
  195. model = IPAddress
  196. fields = ('pk', 'address', 'status', 'vrf', 'tenant', 'device', 'interface', 'description')
  197. row_attrs = {
  198. 'class': lambda record: 'success' if not isinstance(record, IPAddress) else '',
  199. }
  200. class IPAddressBriefTable(BaseTable):
  201. address = tables.LinkColumn('ipam:ipaddress', args=[Accessor('pk')], verbose_name='IP Address')
  202. device = tables.LinkColumn('dcim:device', args=[Accessor('interface.device.pk')], orderable=False,
  203. verbose_name='Device')
  204. interface = tables.Column(orderable=False, verbose_name='Interface')
  205. nat_inside = tables.LinkColumn('ipam:ipaddress', args=[Accessor('nat_inside.pk')], orderable=False,
  206. verbose_name='NAT (Inside)')
  207. class Meta(BaseTable.Meta):
  208. model = IPAddress
  209. fields = ('address', 'device', 'interface', 'nat_inside')
  210. #
  211. # VLAN groups
  212. #
  213. class VLANGroupTable(BaseTable):
  214. pk = ToggleColumn()
  215. name = tables.LinkColumn(verbose_name='Name')
  216. site = tables.LinkColumn('dcim:site', args=[Accessor('site.slug')], verbose_name='Site')
  217. vlan_count = tables.Column(verbose_name='VLANs')
  218. slug = tables.Column(verbose_name='Slug')
  219. actions = tables.TemplateColumn(template_code=VLANGROUP_ACTIONS, attrs={'td': {'class': 'text-right'}},
  220. verbose_name='')
  221. class Meta(BaseTable.Meta):
  222. model = VLANGroup
  223. fields = ('pk', 'name', 'site', 'vlan_count', 'slug', 'actions')
  224. #
  225. # VLANs
  226. #
  227. class VLANTable(BaseTable):
  228. pk = ToggleColumn()
  229. vid = tables.LinkColumn('ipam:vlan', args=[Accessor('pk')], verbose_name='ID')
  230. site = tables.LinkColumn('dcim:site', args=[Accessor('site.slug')], verbose_name='Site')
  231. group = tables.Column(accessor=Accessor('group.name'), verbose_name='Group')
  232. name = tables.Column(verbose_name='Name')
  233. tenant = tables.LinkColumn('tenancy:tenant', args=[Accessor('tenant.slug')], verbose_name='Tenant')
  234. status = tables.TemplateColumn(STATUS_LABEL, verbose_name='Status')
  235. role = tables.Column(verbose_name='Role')
  236. class Meta(BaseTable.Meta):
  237. model = VLAN
  238. fields = ('pk', 'vid', 'site', 'group', 'name', 'tenant', 'status', 'role')