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

1from django.contrib.contenttypes.models import ContentType 

2from django.urls import reverse 

3from django.utils.translation import gettext_lazy as _ 

4 

5from netbox.ui import actions, attrs, panels 

6 

7from .attrs import VRFDisplayAttr 

8 

9 

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 ] 

39 

40 

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') 

46 

47 

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') 

52 

53 

54class RIRPanel(panels.OrganizationalObjectPanel): 

55 is_private = attrs.BooleanAttr('is_private', label=_('Private')) 

56 

57 

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') 

64 

65 

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') 

72 

73 

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') 

85 

86 

87class RolePanel(panels.OrganizationalObjectPanel): 

88 weight = attrs.NumericAttr('weight') 

89 

90 

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') 

108 

109 

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')) 

136 

137 

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')) 

153 

154 

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') 

166 

167 

168class VLANTranslationPolicyPanel(panels.ObjectAttributesPanel): 

169 name = attrs.TextAttr('name') 

170 description = attrs.TextAttr('description') 

171 

172 

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') 

178 

179 

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')) 

186 

187 

188class FHRPGroupAuthPanel(panels.ObjectAttributesPanel): 

189 title = _('Authentication') 

190 

191 auth_type = attrs.ChoiceAttr('auth_type', label=_('Authentication Type')) 

192 auth_key = attrs.TextAttr('auth_key', label=_('Authentication Key')) 

193 

194 

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')) 

208 

209 

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 ) 

231 

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 

235 

236 

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') 

241 

242 

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')