Coverage for ipam/ui/panels.py: 98%
132 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-10 18:35 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-10 18:35 +0000
1from django.contrib.contenttypes.models import ContentType
2from django.urls import reverse
3from django.utils.translation import gettext_lazy as _
5from netbox.ui import actions, attrs, panels
7from .attrs import VRFDisplayAttr
10class FHRPGroupAssignmentsPanel(panels.ObjectPanel):
11 """
12 A panel which lists all FHRP group assignments for a given object.
13 """
14 template_name = 'ipam/panels/fhrp_groups.html'
15 title = _('FHRP Groups')
16 actions = [
17 actions.AddObject(
18 'ipam.FHRPGroup',
19 url_params={
20 'return_url': lambda ctx: reverse(
21 'ipam:fhrpgroupassignment_add',
22 query={
23 'interface_type': ContentType.objects.get_for_model(ctx['object']).pk,
24 'interface_id': ctx['object'].pk,
25 },
26 ),
27 },
28 label=_('Create Group'),
29 ),
30 actions.AddObject(
31 'ipam.FHRPGroupAssignment',
32 url_params={
33 'interface_type': lambda ctx: ContentType.objects.get_for_model(ctx['object']).pk,
34 'interface_id': lambda ctx: ctx['object'].pk,
35 },
36 label=_('Assign Group'),
37 ),
38 ]
41class VRFPanel(panels.ObjectAttributesPanel):
42 rd = attrs.TextAttr('rd', label=_('Route Distinguisher'), style='font-monospace')
43 tenant = attrs.RelatedObjectAttr('tenant', linkify=True, grouped_by='group')
44 enforce_unique = attrs.BooleanAttr('enforce_unique', label=_('Unique IP Space'))
45 description = attrs.TextAttr('description')
48class RouteTargetPanel(panels.ObjectAttributesPanel):
49 name = attrs.TextAttr('name', style='font-monospace')
50 tenant = attrs.RelatedObjectAttr('tenant', linkify=True, grouped_by='group')
51 description = attrs.TextAttr('description')
54class RIRPanel(panels.OrganizationalObjectPanel):
55 is_private = attrs.BooleanAttr('is_private', label=_('Private'))
58class ASNRangePanel(panels.ObjectAttributesPanel):
59 name = attrs.TextAttr('name')
60 rir = attrs.RelatedObjectAttr('rir', linkify=True, label=_('RIR'))
61 range = attrs.TextAttr('range_as_string_with_asdot', label=_('Range'))
62 tenant = attrs.RelatedObjectAttr('tenant', linkify=True, grouped_by='group')
63 description = attrs.TextAttr('description')
66class ASNPanel(panels.ObjectAttributesPanel):
67 asn = attrs.TextAttr('asn_with_asdot', label=_('AS Number'))
68 rir = attrs.RelatedObjectAttr('rir', linkify=True, label=_('RIR'))
69 role = attrs.RelatedObjectAttr('role', linkify=True)
70 tenant = attrs.RelatedObjectAttr('tenant', linkify=True, grouped_by='group')
71 description = attrs.TextAttr('description')
74class AggregatePanel(panels.ObjectAttributesPanel):
75 family = attrs.TextAttr('family', format_string='IPv{}', label=_('Family'))
76 rir = attrs.RelatedObjectAttr('rir', linkify=True, label=_('RIR'))
77 utilization = attrs.TemplatedAttr(
78 'prefix',
79 template_name='ipam/aggregate/attrs/utilization.html',
80 label=_('Utilization'),
81 )
82 tenant = attrs.RelatedObjectAttr('tenant', linkify=True, grouped_by='group')
83 date_added = attrs.DateTimeAttr('date_added', spec='date', label=_('Date Added'))
84 description = attrs.TextAttr('description')
87class RolePanel(panels.OrganizationalObjectPanel):
88 weight = attrs.NumericAttr('weight')
91class IPRangePanel(panels.ObjectAttributesPanel):
92 family = attrs.TextAttr('family', format_string='IPv{}', label=_('Family'))
93 start_address = attrs.TextAttr('start_address', label=_('Starting Address'))
94 end_address = attrs.TextAttr('end_address', label=_('Ending Address'))
95 size = attrs.NumericAttr('size')
96 mark_populated = attrs.BooleanAttr('mark_populated', label=_('Marked Populated'))
97 mark_utilized = attrs.BooleanAttr('mark_utilized', label=_('Marked Utilized'))
98 utilization = attrs.TemplatedAttr(
99 'utilization',
100 template_name='ipam/iprange/attrs/utilization.html',
101 label=_('Utilization'),
102 )
103 vrf = VRFDisplayAttr('vrf', label=_('VRF'), show_rd=True)
104 role = attrs.RelatedObjectAttr('role', linkify=True)
105 status = attrs.ChoiceAttr('status')
106 tenant = attrs.RelatedObjectAttr('tenant', linkify=True, grouped_by='group')
107 description = attrs.TextAttr('description')
110class IPAddressPanel(panels.ObjectAttributesPanel):
111 family = attrs.TextAttr('family', format_string='IPv{}', label=_('Family'))
112 vrf = VRFDisplayAttr('vrf', label=_('VRF'))
113 tenant = attrs.RelatedObjectAttr('tenant', linkify=True, grouped_by='group')
114 status = attrs.ChoiceAttr('status')
115 role = attrs.ChoiceAttr('role')
116 dns_name = attrs.TextAttr('dns_name', label=_('DNS Name'))
117 description = attrs.TextAttr('description')
118 assigned_object = attrs.RelatedObjectAttr(
119 'assigned_object',
120 linkify=True,
121 grouped_by='parent_object',
122 label=_('Assignment'),
123 )
124 nat_inside = attrs.TemplatedAttr(
125 'nat_inside',
126 template_name='ipam/ipaddress/attrs/nat_inside.html',
127 label=_('NAT (inside)'),
128 )
129 nat_outside = attrs.TemplatedAttr(
130 'nat_outside',
131 template_name='ipam/ipaddress/attrs/nat_outside.html',
132 label=_('NAT (outside)'),
133 )
134 is_primary_ip = attrs.BooleanAttr('is_primary_ip', label=_('Primary IP'))
135 is_oob_ip = attrs.BooleanAttr('is_oob_ip', label=_('OOB IP'))
138class PrefixPanel(panels.ObjectAttributesPanel):
139 family = attrs.TextAttr('family', format_string='IPv{}', label=_('Family'))
140 vrf = VRFDisplayAttr('vrf', label=_('VRF'))
141 tenant = attrs.RelatedObjectAttr('tenant', linkify=True, grouped_by='group')
142 aggregate = attrs.TemplatedAttr(
143 'aggregate',
144 template_name='ipam/prefix/attrs/aggregate.html',
145 label=_('Aggregate'),
146 )
147 scope = attrs.GenericForeignKeyAttr('scope', linkify=True, nested=True, max_depth=3)
148 vlan = attrs.RelatedObjectAttr('vlan', linkify=True, label=_('VLAN'), grouped_by='group')
149 status = attrs.ChoiceAttr('status')
150 role = attrs.RelatedObjectAttr('role', linkify=True)
151 description = attrs.TextAttr('description')
152 is_pool = attrs.BooleanAttr('is_pool', label=_('Is a pool'))
155class VLANGroupPanel(panels.ObjectAttributesPanel):
156 name = attrs.TextAttr('name')
157 description = attrs.TextAttr('description')
158 scope = attrs.GenericForeignKeyAttr('scope', linkify=True, nested=True, max_depth=3)
159 vid_ranges = attrs.TemplatedAttr(
160 'vid_ranges_items',
161 template_name='ipam/vlangroup/attrs/vid_ranges.html',
162 label=_('VLAN IDs'),
163 )
164 utilization = attrs.UtilizationAttr('utilization')
165 tenant = attrs.RelatedObjectAttr('tenant', linkify=True, grouped_by='group')
168class VLANTranslationPolicyPanel(panels.ObjectAttributesPanel):
169 name = attrs.TextAttr('name')
170 description = attrs.TextAttr('description')
173class VLANTranslationRulePanel(panels.ObjectAttributesPanel):
174 policy = attrs.RelatedObjectAttr('policy', linkify=True)
175 local_vid = attrs.NumericAttr('local_vid', label=_('Local VID'))
176 remote_vid = attrs.NumericAttr('remote_vid', label=_('Remote VID'))
177 description = attrs.TextAttr('description')
180class FHRPGroupPanel(panels.ObjectAttributesPanel):
181 protocol = attrs.ChoiceAttr('protocol')
182 group_id = attrs.NumericAttr('group_id', label=_('Group ID'))
183 name = attrs.TextAttr('name')
184 description = attrs.TextAttr('description')
185 member_count = attrs.NumericAttr('member_count', label=_('Members'))
188class FHRPGroupAuthPanel(panels.ObjectAttributesPanel):
189 title = _('Authentication')
191 auth_type = attrs.ChoiceAttr('auth_type', label=_('Authentication Type'))
192 auth_key = attrs.TextAttr('auth_key', label=_('Authentication Key'))
195class VLANPanel(panels.ObjectAttributesPanel):
196 region = attrs.NestedObjectAttr('site.region', linkify=True, label=_('Region'))
197 site = attrs.RelatedObjectAttr('site', linkify=True)
198 group = attrs.RelatedObjectAttr('group', linkify=True)
199 vid = attrs.NumericAttr('vid', label=_('VLAN ID'))
200 name = attrs.TextAttr('name')
201 tenant = attrs.RelatedObjectAttr('tenant', linkify=True, grouped_by='group')
202 status = attrs.ChoiceAttr('status')
203 role = attrs.RelatedObjectAttr('role', linkify=True)
204 description = attrs.TextAttr('description')
205 qinq_role = attrs.ChoiceAttr('qinq_role', label=_('Q-in-Q Role'))
206 qinq_svlan = attrs.RelatedObjectAttr('qinq_svlan', linkify=True, label=_('Q-in-Q SVLAN'))
207 l2vpn = attrs.RelatedObjectAttr('l2vpn_termination.l2vpn', linkify=True, label=_('L2VPN'))
210class VLANCustomerVLANsPanel(panels.ObjectsTablePanel):
211 """
212 A panel listing customer VLANs (C-VLANs) for an S-VLAN. Only renders when the VLAN has Q-in-Q
213 role 'svlan'.
214 """
215 def __init__(self):
216 super().__init__(
217 'ipam.vlan',
218 filters={'qinq_svlan_id': lambda ctx: ctx['object'].pk},
219 title=_('Customer VLANs'),
220 actions=[
221 actions.AddObject(
222 'ipam.vlan',
223 url_params={
224 'qinq_role': 'cvlan',
225 'qinq_svlan': lambda ctx: ctx['object'].pk,
226 },
227 label=_('Add a VLAN'),
228 ),
229 ],
230 )
232 def should_render(self, context):
233 obj = context.get('object')
234 return False if (obj is None or obj.qinq_role != 'svlan') else True
237class ServiceTemplatePanel(panels.ObjectAttributesPanel):
238 name = attrs.TextAttr('name')
239 port_mappings = attrs.TextAttr('port_mappings_list', label=_('Port Mappings'))
240 description = attrs.TextAttr('description')
243class ServicePanel(panels.ObjectAttributesPanel):
244 name = attrs.TextAttr('name')
245 parent = attrs.RelatedObjectAttr('parent', linkify=True)
246 port_mappings = attrs.TextAttr('port_mappings_list', label=_('Port Mappings'))
247 ip_addresses = attrs.TemplatedAttr(
248 'ipaddresses',
249 template_name='ipam/service/attrs/ip_addresses.html',
250 label=_('IP Addresses'),
251 )
252 description = attrs.TextAttr('description')