netbox-pathways 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- netbox_pathways/__init__.py +91 -0
- netbox_pathways/api/__init__.py +0 -0
- netbox_pathways/api/external_geo.py +134 -0
- netbox_pathways/api/geo.py +360 -0
- netbox_pathways/api/serializers.py +520 -0
- netbox_pathways/api/traversal.py +48 -0
- netbox_pathways/api/urls.py +46 -0
- netbox_pathways/api/views.py +140 -0
- netbox_pathways/choices.py +122 -0
- netbox_pathways/filterforms.py +381 -0
- netbox_pathways/filters.py +622 -0
- netbox_pathways/forms.py +1020 -0
- netbox_pathways/geo.py +79 -0
- netbox_pathways/graph.py +545 -0
- netbox_pathways/management/__init__.py +0 -0
- netbox_pathways/management/commands/__init__.py +0 -0
- netbox_pathways/management/commands/_geodata_worker.py +54 -0
- netbox_pathways/management/commands/generate_qgis_project.py +141 -0
- netbox_pathways/management/commands/generate_sample_data.py +550 -0
- netbox_pathways/management/commands/import_geodata.py +705 -0
- netbox_pathways/migrations/0001_initial.py +291 -0
- netbox_pathways/migrations/0002_replace_owner_with_tenant.py +54 -0
- netbox_pathways/migrations/0003_structure_optional_site_dimensions.py +40 -0
- netbox_pathways/migrations/0004_circuit_geometry.py +40 -0
- netbox_pathways/migrations/0005_replace_unique_together_with_constraints.py +39 -0
- netbox_pathways/migrations/0006_remove_cablesegment_sequence_enter_exit.py +33 -0
- netbox_pathways/migrations/0007_cable_routing_redesign.py +36 -0
- netbox_pathways/migrations/0008_conduitbank_pathway_subclass.py +108 -0
- netbox_pathways/migrations/0009_remove_conduit_unique_position_per_bank_and_more.py +21 -0
- netbox_pathways/migrations/0010_structure_status.py +18 -0
- netbox_pathways/migrations/0011_rename_name_to_label.py +42 -0
- netbox_pathways/migrations/0012_add_filter_field_indexes.py +28 -0
- netbox_pathways/migrations/0013_plannedroute.py +45 -0
- netbox_pathways/migrations/0014_plannedroute_parent_split.py +19 -0
- netbox_pathways/migrations/__init__.py +1 -0
- netbox_pathways/models.py +879 -0
- netbox_pathways/navigation.py +207 -0
- netbox_pathways/registry.py +195 -0
- netbox_pathways/route_engine.py +255 -0
- netbox_pathways/routing.py +102 -0
- netbox_pathways/search.py +126 -0
- netbox_pathways/signals.py +24 -0
- netbox_pathways/static/netbox_pathways/css/leaflet-theme.css +375 -0
- netbox_pathways/static/netbox_pathways/css/pathways-map.css +68 -0
- netbox_pathways/static/netbox_pathways/qgis/pathways.qml +34 -0
- netbox_pathways/static/netbox_pathways/qgis/structures.qml +38 -0
- netbox_pathways/static/netbox_pathways/vendor/MarkerCluster.Default.css +60 -0
- netbox_pathways/static/netbox_pathways/vendor/MarkerCluster.css +14 -0
- netbox_pathways/static/netbox_pathways/vendor/leaflet.markercluster.js +2 -0
- netbox_pathways/tables.py +459 -0
- netbox_pathways/template_content.py +337 -0
- netbox_pathways/templates/netbox_pathways/aerialspan.html +1 -0
- netbox_pathways/templates/netbox_pathways/buttons/apply_route.html +5 -0
- netbox_pathways/templates/netbox_pathways/buttons/replan_route.html +5 -0
- netbox_pathways/templates/netbox_pathways/buttons/revert_split.html +9 -0
- netbox_pathways/templates/netbox_pathways/buttons/split_route.html +5 -0
- netbox_pathways/templates/netbox_pathways/buttons/view_in_map.html +5 -0
- netbox_pathways/templates/netbox_pathways/cable_route_tab.html +46 -0
- netbox_pathways/templates/netbox_pathways/cablesegment.html +32 -0
- netbox_pathways/templates/netbox_pathways/conduit.html +1 -0
- netbox_pathways/templates/netbox_pathways/conduitbank.html +1 -0
- netbox_pathways/templates/netbox_pathways/conduitjunction.html +1 -0
- netbox_pathways/templates/netbox_pathways/directburied.html +1 -0
- netbox_pathways/templates/netbox_pathways/inc/cable_add_segment_form.html +23 -0
- netbox_pathways/templates/netbox_pathways/inc/cable_route_finder_results.html +47 -0
- netbox_pathways/templates/netbox_pathways/inc/cable_routing_panel.html +40 -0
- netbox_pathways/templates/netbox_pathways/inc/cable_segment_table.html +97 -0
- netbox_pathways/templates/netbox_pathways/inc/connected_structures_panel.html +9 -0
- netbox_pathways/templates/netbox_pathways/inc/constraint_card.html +22 -0
- netbox_pathways/templates/netbox_pathways/inc/geo_map_panel.html +53 -0
- netbox_pathways/templates/netbox_pathways/inc/plannedroute_map_panel.html +31 -0
- netbox_pathways/templates/netbox_pathways/inc/planner_results.html +80 -0
- netbox_pathways/templates/netbox_pathways/innerduct.html +1 -0
- netbox_pathways/templates/netbox_pathways/map.html +518 -0
- netbox_pathways/templates/netbox_pathways/pathway.html +1 -0
- netbox_pathways/templates/netbox_pathways/pathwaylocation.html +1 -0
- netbox_pathways/templates/netbox_pathways/plannedroute.html +110 -0
- netbox_pathways/templates/netbox_pathways/plannedroute_apply.html +56 -0
- netbox_pathways/templates/netbox_pathways/plannedroute_split.html +53 -0
- netbox_pathways/templates/netbox_pathways/pullsheet_detail.html +134 -0
- netbox_pathways/templates/netbox_pathways/pullsheet_list.html +15 -0
- netbox_pathways/templates/netbox_pathways/route_planner.html +713 -0
- netbox_pathways/templates/netbox_pathways/sitegeometry.html +1 -0
- netbox_pathways/templates/netbox_pathways/structure.html +13 -0
- netbox_pathways/templates/netbox_pathways/widgets/map_widget.html +10 -0
- netbox_pathways/ui/__init__.py +0 -0
- netbox_pathways/ui/panels.py +148 -0
- netbox_pathways/urls.py +243 -0
- netbox_pathways/views.py +2264 -0
- netbox_pathways-0.1.0.dist-info/METADATA +145 -0
- netbox_pathways-0.1.0.dist-info/RECORD +93 -0
- netbox_pathways-0.1.0.dist-info/WHEEL +5 -0
- netbox_pathways-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,520 @@
|
|
|
1
|
+
from circuits.api.serializers_.circuits import CircuitSerializer
|
|
2
|
+
from dcim.api.serializers_.cables import CableSerializer
|
|
3
|
+
from dcim.api.serializers_.sites import LocationSerializer, SiteSerializer
|
|
4
|
+
from netbox.api.fields import ChoiceField
|
|
5
|
+
from netbox.api.serializers import NetBoxModelSerializer
|
|
6
|
+
from rest_framework import serializers as drf_serializers
|
|
7
|
+
from tenancy.api.serializers_.tenants import TenantSerializer
|
|
8
|
+
|
|
9
|
+
from ..choices import (
|
|
10
|
+
AerialTypeChoices,
|
|
11
|
+
BankFaceChoices,
|
|
12
|
+
ConduitBankConfigChoices,
|
|
13
|
+
ConduitMaterialChoices,
|
|
14
|
+
EncasementTypeChoices,
|
|
15
|
+
PathwayTypeChoices,
|
|
16
|
+
PlannedRouteStatusChoices,
|
|
17
|
+
StructureStatusChoices,
|
|
18
|
+
StructureTypeChoices,
|
|
19
|
+
)
|
|
20
|
+
from ..models import (
|
|
21
|
+
AerialSpan,
|
|
22
|
+
CableSegment,
|
|
23
|
+
CircuitGeometry,
|
|
24
|
+
Conduit,
|
|
25
|
+
ConduitBank,
|
|
26
|
+
ConduitJunction,
|
|
27
|
+
DirectBuried,
|
|
28
|
+
Innerduct,
|
|
29
|
+
Pathway,
|
|
30
|
+
PathwayLocation,
|
|
31
|
+
PlannedRoute,
|
|
32
|
+
SiteGeometry,
|
|
33
|
+
Structure,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class StructureSerializer(NetBoxModelSerializer):
|
|
38
|
+
url = drf_serializers.HyperlinkedIdentityField(
|
|
39
|
+
view_name="plugins-api:netbox_pathways-api:structure-detail",
|
|
40
|
+
)
|
|
41
|
+
status = ChoiceField(choices=StructureStatusChoices, required=False)
|
|
42
|
+
structure_type = ChoiceField(choices=StructureTypeChoices, required=False, allow_blank=True)
|
|
43
|
+
site = SiteSerializer(nested=True, required=False, allow_null=True)
|
|
44
|
+
tenant = TenantSerializer(nested=True, required=False, allow_null=True)
|
|
45
|
+
no_pathways = drf_serializers.SerializerMethodField(read_only=True)
|
|
46
|
+
description = drf_serializers.SerializerMethodField(read_only=True)
|
|
47
|
+
|
|
48
|
+
class Meta:
|
|
49
|
+
model = Structure
|
|
50
|
+
fields = [
|
|
51
|
+
"id",
|
|
52
|
+
"url",
|
|
53
|
+
"display_url",
|
|
54
|
+
"display",
|
|
55
|
+
"name",
|
|
56
|
+
"status",
|
|
57
|
+
"structure_type",
|
|
58
|
+
"site",
|
|
59
|
+
"location",
|
|
60
|
+
"height",
|
|
61
|
+
"width",
|
|
62
|
+
"length",
|
|
63
|
+
"depth",
|
|
64
|
+
"elevation",
|
|
65
|
+
"installation_date",
|
|
66
|
+
"tenant",
|
|
67
|
+
"access_notes",
|
|
68
|
+
"comments",
|
|
69
|
+
"tags",
|
|
70
|
+
"created",
|
|
71
|
+
"last_updated",
|
|
72
|
+
"no_pathways",
|
|
73
|
+
"description",
|
|
74
|
+
]
|
|
75
|
+
brief_fields = (
|
|
76
|
+
"id",
|
|
77
|
+
"url",
|
|
78
|
+
"display_url",
|
|
79
|
+
"display",
|
|
80
|
+
"label",
|
|
81
|
+
"structure_type",
|
|
82
|
+
"no_pathways",
|
|
83
|
+
"description",
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
def get_no_pathways(self, obj):
|
|
87
|
+
if hasattr(obj, "_has_pathways"):
|
|
88
|
+
return not obj._has_pathways
|
|
89
|
+
return None
|
|
90
|
+
|
|
91
|
+
def get_description(self, obj):
|
|
92
|
+
if hasattr(obj, "_has_pathways") and not obj._has_pathways:
|
|
93
|
+
return "No connected pathways"
|
|
94
|
+
return None
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
# --- Shared FK field declarations for pathway subtypes ---
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def _pathway_fk_fields():
|
|
101
|
+
"""Common FK field declarations for all pathway-based serializers."""
|
|
102
|
+
return {
|
|
103
|
+
"start_structure": StructureSerializer(nested=True, required=False, allow_null=True),
|
|
104
|
+
"end_structure": StructureSerializer(nested=True, required=False, allow_null=True),
|
|
105
|
+
"start_location": LocationSerializer(nested=True, required=False, allow_null=True),
|
|
106
|
+
"end_location": LocationSerializer(nested=True, required=False, allow_null=True),
|
|
107
|
+
"tenant": TenantSerializer(nested=True, required=False, allow_null=True),
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
class ConduitBankSerializer(NetBoxModelSerializer):
|
|
112
|
+
url = drf_serializers.HyperlinkedIdentityField(
|
|
113
|
+
view_name="plugins-api:netbox_pathways-api:conduitbank-detail",
|
|
114
|
+
)
|
|
115
|
+
start_structure = StructureSerializer(nested=True, required=False, allow_null=True)
|
|
116
|
+
end_structure = StructureSerializer(nested=True, required=False, allow_null=True)
|
|
117
|
+
start_face = ChoiceField(choices=BankFaceChoices, required=False, allow_blank=True)
|
|
118
|
+
end_face = ChoiceField(choices=BankFaceChoices, required=False, allow_blank=True)
|
|
119
|
+
configuration = ChoiceField(choices=ConduitBankConfigChoices, required=False, allow_blank=True)
|
|
120
|
+
encasement_type = ChoiceField(choices=EncasementTypeChoices, required=False, allow_blank=True)
|
|
121
|
+
tenant = TenantSerializer(nested=True, required=False, allow_null=True)
|
|
122
|
+
|
|
123
|
+
class Meta:
|
|
124
|
+
model = ConduitBank
|
|
125
|
+
fields = [
|
|
126
|
+
"id",
|
|
127
|
+
"url",
|
|
128
|
+
"display_url",
|
|
129
|
+
"display",
|
|
130
|
+
"label",
|
|
131
|
+
"start_structure",
|
|
132
|
+
"end_structure",
|
|
133
|
+
"start_face",
|
|
134
|
+
"end_face",
|
|
135
|
+
"tenant",
|
|
136
|
+
"path",
|
|
137
|
+
"length",
|
|
138
|
+
"configuration",
|
|
139
|
+
"total_conduits",
|
|
140
|
+
"encasement_type",
|
|
141
|
+
"installation_date",
|
|
142
|
+
"comments",
|
|
143
|
+
"tags",
|
|
144
|
+
"created",
|
|
145
|
+
"last_updated",
|
|
146
|
+
]
|
|
147
|
+
brief_fields = ("id", "url", "display_url", "display", "label")
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
class PathwaySerializer(NetBoxModelSerializer):
|
|
151
|
+
url = drf_serializers.HyperlinkedIdentityField(
|
|
152
|
+
view_name="plugins-api:netbox_pathways-api:pathway-detail",
|
|
153
|
+
)
|
|
154
|
+
pathway_type = ChoiceField(choices=PathwayTypeChoices, required=False, allow_blank=True)
|
|
155
|
+
start_structure = StructureSerializer(nested=True, required=False, allow_null=True)
|
|
156
|
+
end_structure = StructureSerializer(nested=True, required=False, allow_null=True)
|
|
157
|
+
start_location = LocationSerializer(nested=True, required=False, allow_null=True)
|
|
158
|
+
end_location = LocationSerializer(nested=True, required=False, allow_null=True)
|
|
159
|
+
tenant = TenantSerializer(nested=True, required=False, allow_null=True)
|
|
160
|
+
cables_routed = drf_serializers.IntegerField(read_only=True)
|
|
161
|
+
|
|
162
|
+
class Meta:
|
|
163
|
+
model = Pathway
|
|
164
|
+
fields = [
|
|
165
|
+
"id",
|
|
166
|
+
"url",
|
|
167
|
+
"display_url",
|
|
168
|
+
"display",
|
|
169
|
+
"label",
|
|
170
|
+
"pathway_type",
|
|
171
|
+
"path",
|
|
172
|
+
"start_structure",
|
|
173
|
+
"end_structure",
|
|
174
|
+
"start_location",
|
|
175
|
+
"end_location",
|
|
176
|
+
"tenant",
|
|
177
|
+
"length",
|
|
178
|
+
"cables_routed",
|
|
179
|
+
"installation_date",
|
|
180
|
+
"comments",
|
|
181
|
+
"tags",
|
|
182
|
+
"created",
|
|
183
|
+
"last_updated",
|
|
184
|
+
]
|
|
185
|
+
brief_fields = ("id", "url", "display_url", "display", "label", "pathway_type")
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
class ConduitSerializer(NetBoxModelSerializer):
|
|
189
|
+
url = drf_serializers.HyperlinkedIdentityField(
|
|
190
|
+
view_name="plugins-api:netbox_pathways-api:conduit-detail",
|
|
191
|
+
)
|
|
192
|
+
material = ChoiceField(choices=ConduitMaterialChoices, required=False, allow_blank=True)
|
|
193
|
+
start_structure = StructureSerializer(nested=True, required=False, allow_null=True)
|
|
194
|
+
end_structure = StructureSerializer(nested=True, required=False, allow_null=True)
|
|
195
|
+
start_location = LocationSerializer(nested=True, required=False, allow_null=True)
|
|
196
|
+
end_location = LocationSerializer(nested=True, required=False, allow_null=True)
|
|
197
|
+
conduit_bank = ConduitBankSerializer(nested=True, required=False, allow_null=True)
|
|
198
|
+
tenant = TenantSerializer(nested=True, required=False, allow_null=True)
|
|
199
|
+
cables_routed = drf_serializers.IntegerField(read_only=True)
|
|
200
|
+
|
|
201
|
+
class Meta:
|
|
202
|
+
model = Conduit
|
|
203
|
+
fields = [
|
|
204
|
+
"id",
|
|
205
|
+
"url",
|
|
206
|
+
"display_url",
|
|
207
|
+
"display",
|
|
208
|
+
"label",
|
|
209
|
+
"pathway_type",
|
|
210
|
+
"path",
|
|
211
|
+
"start_structure",
|
|
212
|
+
"end_structure",
|
|
213
|
+
"start_location",
|
|
214
|
+
"end_location",
|
|
215
|
+
"material",
|
|
216
|
+
"inner_diameter",
|
|
217
|
+
"outer_diameter",
|
|
218
|
+
"depth",
|
|
219
|
+
"conduit_bank",
|
|
220
|
+
"bank_position",
|
|
221
|
+
"start_junction",
|
|
222
|
+
"end_junction",
|
|
223
|
+
"length",
|
|
224
|
+
"cables_routed",
|
|
225
|
+
"installation_date",
|
|
226
|
+
"comments",
|
|
227
|
+
"tags",
|
|
228
|
+
"created",
|
|
229
|
+
"last_updated",
|
|
230
|
+
]
|
|
231
|
+
brief_fields = ("id", "url", "display_url", "display", "label", "material")
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
class AerialSpanSerializer(NetBoxModelSerializer):
|
|
235
|
+
url = drf_serializers.HyperlinkedIdentityField(
|
|
236
|
+
view_name="plugins-api:netbox_pathways-api:aerialspan-detail",
|
|
237
|
+
)
|
|
238
|
+
aerial_type = ChoiceField(choices=AerialTypeChoices, required=False, allow_blank=True)
|
|
239
|
+
start_structure = StructureSerializer(nested=True, required=False, allow_null=True)
|
|
240
|
+
end_structure = StructureSerializer(nested=True, required=False, allow_null=True)
|
|
241
|
+
start_location = LocationSerializer(nested=True, required=False, allow_null=True)
|
|
242
|
+
end_location = LocationSerializer(nested=True, required=False, allow_null=True)
|
|
243
|
+
tenant = TenantSerializer(nested=True, required=False, allow_null=True)
|
|
244
|
+
cables_routed = drf_serializers.IntegerField(read_only=True)
|
|
245
|
+
|
|
246
|
+
class Meta:
|
|
247
|
+
model = AerialSpan
|
|
248
|
+
fields = [
|
|
249
|
+
"id",
|
|
250
|
+
"url",
|
|
251
|
+
"display_url",
|
|
252
|
+
"display",
|
|
253
|
+
"label",
|
|
254
|
+
"pathway_type",
|
|
255
|
+
"path",
|
|
256
|
+
"start_structure",
|
|
257
|
+
"end_structure",
|
|
258
|
+
"start_location",
|
|
259
|
+
"end_location",
|
|
260
|
+
"aerial_type",
|
|
261
|
+
"attachment_height",
|
|
262
|
+
"sag",
|
|
263
|
+
"messenger_size",
|
|
264
|
+
"wind_loading",
|
|
265
|
+
"ice_loading",
|
|
266
|
+
"length",
|
|
267
|
+
"cables_routed",
|
|
268
|
+
"installation_date",
|
|
269
|
+
"comments",
|
|
270
|
+
"tags",
|
|
271
|
+
"created",
|
|
272
|
+
"last_updated",
|
|
273
|
+
]
|
|
274
|
+
brief_fields = ("id", "url", "display_url", "display", "label", "aerial_type")
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
class DirectBuriedSerializer(NetBoxModelSerializer):
|
|
278
|
+
url = drf_serializers.HyperlinkedIdentityField(
|
|
279
|
+
view_name="plugins-api:netbox_pathways-api:directburied-detail",
|
|
280
|
+
)
|
|
281
|
+
start_structure = StructureSerializer(nested=True, required=False, allow_null=True)
|
|
282
|
+
end_structure = StructureSerializer(nested=True, required=False, allow_null=True)
|
|
283
|
+
start_location = LocationSerializer(nested=True, required=False, allow_null=True)
|
|
284
|
+
end_location = LocationSerializer(nested=True, required=False, allow_null=True)
|
|
285
|
+
tenant = TenantSerializer(nested=True, required=False, allow_null=True)
|
|
286
|
+
cables_routed = drf_serializers.IntegerField(read_only=True)
|
|
287
|
+
|
|
288
|
+
class Meta:
|
|
289
|
+
model = DirectBuried
|
|
290
|
+
fields = [
|
|
291
|
+
"id",
|
|
292
|
+
"url",
|
|
293
|
+
"display_url",
|
|
294
|
+
"display",
|
|
295
|
+
"label",
|
|
296
|
+
"pathway_type",
|
|
297
|
+
"path",
|
|
298
|
+
"start_structure",
|
|
299
|
+
"end_structure",
|
|
300
|
+
"start_location",
|
|
301
|
+
"end_location",
|
|
302
|
+
"burial_depth",
|
|
303
|
+
"warning_tape",
|
|
304
|
+
"tracer_wire",
|
|
305
|
+
"armor_type",
|
|
306
|
+
"length",
|
|
307
|
+
"cables_routed",
|
|
308
|
+
"installation_date",
|
|
309
|
+
"comments",
|
|
310
|
+
"tags",
|
|
311
|
+
"created",
|
|
312
|
+
"last_updated",
|
|
313
|
+
]
|
|
314
|
+
brief_fields = ("id", "url", "display_url", "display", "label")
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
class InnerductSerializer(NetBoxModelSerializer):
|
|
318
|
+
url = drf_serializers.HyperlinkedIdentityField(
|
|
319
|
+
view_name="plugins-api:netbox_pathways-api:innerduct-detail",
|
|
320
|
+
)
|
|
321
|
+
start_structure = StructureSerializer(nested=True, required=False, allow_null=True)
|
|
322
|
+
end_structure = StructureSerializer(nested=True, required=False, allow_null=True)
|
|
323
|
+
start_location = LocationSerializer(nested=True, required=False, allow_null=True)
|
|
324
|
+
end_location = LocationSerializer(nested=True, required=False, allow_null=True)
|
|
325
|
+
parent_conduit = ConduitSerializer(nested=True, required=False, allow_null=True)
|
|
326
|
+
cables_routed = drf_serializers.IntegerField(read_only=True)
|
|
327
|
+
|
|
328
|
+
class Meta:
|
|
329
|
+
model = Innerduct
|
|
330
|
+
fields = [
|
|
331
|
+
"id",
|
|
332
|
+
"url",
|
|
333
|
+
"display_url",
|
|
334
|
+
"display",
|
|
335
|
+
"label",
|
|
336
|
+
"pathway_type",
|
|
337
|
+
"path",
|
|
338
|
+
"start_structure",
|
|
339
|
+
"end_structure",
|
|
340
|
+
"start_location",
|
|
341
|
+
"end_location",
|
|
342
|
+
"parent_conduit",
|
|
343
|
+
"size",
|
|
344
|
+
"color",
|
|
345
|
+
"position",
|
|
346
|
+
"length",
|
|
347
|
+
"cables_routed",
|
|
348
|
+
"installation_date",
|
|
349
|
+
"comments",
|
|
350
|
+
"tags",
|
|
351
|
+
"created",
|
|
352
|
+
"last_updated",
|
|
353
|
+
]
|
|
354
|
+
brief_fields = ("id", "url", "display_url", "display", "label", "size")
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
class ConduitJunctionSerializer(NetBoxModelSerializer):
|
|
358
|
+
url = drf_serializers.HyperlinkedIdentityField(
|
|
359
|
+
view_name="plugins-api:netbox_pathways-api:conduitjunction-detail",
|
|
360
|
+
)
|
|
361
|
+
trunk_conduit = ConduitSerializer(nested=True, required=False, allow_null=True)
|
|
362
|
+
branch_conduit = ConduitSerializer(nested=True, required=False, allow_null=True)
|
|
363
|
+
towards_structure = StructureSerializer(nested=True, required=False, allow_null=True)
|
|
364
|
+
|
|
365
|
+
class Meta:
|
|
366
|
+
model = ConduitJunction
|
|
367
|
+
fields = [
|
|
368
|
+
"id",
|
|
369
|
+
"url",
|
|
370
|
+
"display_url",
|
|
371
|
+
"display",
|
|
372
|
+
"label",
|
|
373
|
+
"trunk_conduit",
|
|
374
|
+
"branch_conduit",
|
|
375
|
+
"towards_structure",
|
|
376
|
+
"position_on_trunk",
|
|
377
|
+
"comments",
|
|
378
|
+
"tags",
|
|
379
|
+
"created",
|
|
380
|
+
"last_updated",
|
|
381
|
+
]
|
|
382
|
+
brief_fields = ("id", "url", "display_url", "display", "label")
|
|
383
|
+
|
|
384
|
+
|
|
385
|
+
class PathwayLocationSerializer(NetBoxModelSerializer):
|
|
386
|
+
url = drf_serializers.HyperlinkedIdentityField(
|
|
387
|
+
view_name="plugins-api:netbox_pathways-api:pathwaylocation-detail",
|
|
388
|
+
)
|
|
389
|
+
pathway = PathwaySerializer(nested=True, required=False, allow_null=True)
|
|
390
|
+
site = SiteSerializer(nested=True, required=False, allow_null=True)
|
|
391
|
+
location = LocationSerializer(nested=True, required=False, allow_null=True)
|
|
392
|
+
|
|
393
|
+
class Meta:
|
|
394
|
+
model = PathwayLocation
|
|
395
|
+
fields = [
|
|
396
|
+
"id",
|
|
397
|
+
"url",
|
|
398
|
+
"display_url",
|
|
399
|
+
"display",
|
|
400
|
+
"pathway",
|
|
401
|
+
"site",
|
|
402
|
+
"location",
|
|
403
|
+
"sequence",
|
|
404
|
+
"comments",
|
|
405
|
+
"tags",
|
|
406
|
+
"created",
|
|
407
|
+
"last_updated",
|
|
408
|
+
]
|
|
409
|
+
brief_fields = ("id", "url", "display_url", "display", "pathway", "sequence")
|
|
410
|
+
|
|
411
|
+
|
|
412
|
+
class CableSegmentSerializer(NetBoxModelSerializer):
|
|
413
|
+
url = drf_serializers.HyperlinkedIdentityField(
|
|
414
|
+
view_name="plugins-api:netbox_pathways-api:cablesegment-detail",
|
|
415
|
+
)
|
|
416
|
+
cable = CableSerializer(nested=True, required=False, allow_null=True)
|
|
417
|
+
pathway = PathwaySerializer(nested=True, required=False, allow_null=True)
|
|
418
|
+
|
|
419
|
+
class Meta:
|
|
420
|
+
model = CableSegment
|
|
421
|
+
fields = [
|
|
422
|
+
"id",
|
|
423
|
+
"url",
|
|
424
|
+
"display_url",
|
|
425
|
+
"display",
|
|
426
|
+
"cable",
|
|
427
|
+
"pathway",
|
|
428
|
+
"sequence",
|
|
429
|
+
"comments",
|
|
430
|
+
"tags",
|
|
431
|
+
"created",
|
|
432
|
+
"last_updated",
|
|
433
|
+
]
|
|
434
|
+
brief_fields = ("id", "url", "display_url", "display", "cable", "pathway", "sequence")
|
|
435
|
+
|
|
436
|
+
|
|
437
|
+
class SiteGeometrySerializer(NetBoxModelSerializer):
|
|
438
|
+
url = drf_serializers.HyperlinkedIdentityField(
|
|
439
|
+
view_name="plugins-api:netbox_pathways-api:sitegeometry-detail",
|
|
440
|
+
)
|
|
441
|
+
site = SiteSerializer(nested=True, required=False, allow_null=True)
|
|
442
|
+
structure = StructureSerializer(nested=True, required=False, allow_null=True)
|
|
443
|
+
|
|
444
|
+
class Meta:
|
|
445
|
+
model = SiteGeometry
|
|
446
|
+
fields = [
|
|
447
|
+
"id",
|
|
448
|
+
"url",
|
|
449
|
+
"display_url",
|
|
450
|
+
"display",
|
|
451
|
+
"site",
|
|
452
|
+
"structure",
|
|
453
|
+
"geometry",
|
|
454
|
+
"comments",
|
|
455
|
+
"tags",
|
|
456
|
+
"created",
|
|
457
|
+
"last_updated",
|
|
458
|
+
]
|
|
459
|
+
brief_fields = ("id", "url", "display_url", "display", "site")
|
|
460
|
+
|
|
461
|
+
|
|
462
|
+
class CircuitGeometrySerializer(NetBoxModelSerializer):
|
|
463
|
+
url = drf_serializers.HyperlinkedIdentityField(
|
|
464
|
+
view_name="plugins-api:netbox_pathways-api:circuitgeometry-detail",
|
|
465
|
+
)
|
|
466
|
+
circuit = CircuitSerializer(nested=True, required=False, allow_null=True)
|
|
467
|
+
|
|
468
|
+
class Meta:
|
|
469
|
+
model = CircuitGeometry
|
|
470
|
+
fields = [
|
|
471
|
+
"id",
|
|
472
|
+
"url",
|
|
473
|
+
"display_url",
|
|
474
|
+
"display",
|
|
475
|
+
"circuit",
|
|
476
|
+
"path",
|
|
477
|
+
"provider_reference",
|
|
478
|
+
"comments",
|
|
479
|
+
"tags",
|
|
480
|
+
"created",
|
|
481
|
+
"last_updated",
|
|
482
|
+
]
|
|
483
|
+
brief_fields = ("id", "url", "display_url", "display", "circuit")
|
|
484
|
+
|
|
485
|
+
|
|
486
|
+
class PlannedRouteSerializer(NetBoxModelSerializer):
|
|
487
|
+
url = drf_serializers.HyperlinkedIdentityField(
|
|
488
|
+
view_name="plugins-api:netbox_pathways-api:plannedroute-detail",
|
|
489
|
+
)
|
|
490
|
+
status = ChoiceField(choices=PlannedRouteStatusChoices, required=False)
|
|
491
|
+
start_structure = StructureSerializer(nested=True, required=False, allow_null=True)
|
|
492
|
+
end_structure = StructureSerializer(nested=True, required=False, allow_null=True)
|
|
493
|
+
start_location = LocationSerializer(nested=True, required=False, allow_null=True)
|
|
494
|
+
end_location = LocationSerializer(nested=True, required=False, allow_null=True)
|
|
495
|
+
tenant = TenantSerializer(nested=True, required=False, allow_null=True)
|
|
496
|
+
cable = CableSerializer(nested=True, required=False, allow_null=True)
|
|
497
|
+
|
|
498
|
+
class Meta:
|
|
499
|
+
model = PlannedRoute
|
|
500
|
+
fields = [
|
|
501
|
+
"id",
|
|
502
|
+
"url",
|
|
503
|
+
"display_url",
|
|
504
|
+
"display",
|
|
505
|
+
"name",
|
|
506
|
+
"status",
|
|
507
|
+
"start_structure",
|
|
508
|
+
"end_structure",
|
|
509
|
+
"start_location",
|
|
510
|
+
"end_location",
|
|
511
|
+
"pathway_ids",
|
|
512
|
+
"constraints",
|
|
513
|
+
"tenant",
|
|
514
|
+
"cable",
|
|
515
|
+
"comments",
|
|
516
|
+
"tags",
|
|
517
|
+
"created",
|
|
518
|
+
"last_updated",
|
|
519
|
+
]
|
|
520
|
+
brief_fields = ("id", "url", "display_url", "display", "name", "status")
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""
|
|
2
|
+
REST API endpoints for graph traversal operations.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from rest_framework import status
|
|
6
|
+
from rest_framework.permissions import IsAuthenticated
|
|
7
|
+
from rest_framework.response import Response
|
|
8
|
+
from rest_framework.views import APIView
|
|
9
|
+
|
|
10
|
+
from ..graph import trace_cable
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class CableTraceView(APIView):
|
|
14
|
+
"""
|
|
15
|
+
Trace a cable's physical route through pathways.
|
|
16
|
+
|
|
17
|
+
GET /api/plugins/netbox-pathways/traversal/cable-trace/?cable_id=<id>
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
permission_classes = [IsAuthenticated]
|
|
21
|
+
|
|
22
|
+
def get(self, request):
|
|
23
|
+
cable_id = request.query_params.get("cable_id")
|
|
24
|
+
if not cable_id:
|
|
25
|
+
return Response(
|
|
26
|
+
{"error": "cable_id is required"},
|
|
27
|
+
status=status.HTTP_400_BAD_REQUEST,
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
try:
|
|
31
|
+
cable_id = int(cable_id)
|
|
32
|
+
except (TypeError, ValueError):
|
|
33
|
+
return Response(
|
|
34
|
+
{"error": "cable_id must be an integer"},
|
|
35
|
+
status=status.HTTP_400_BAD_REQUEST,
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
segments = trace_cable(cable_id)
|
|
39
|
+
total_length = sum(s["length"] or 0 for s in segments)
|
|
40
|
+
|
|
41
|
+
return Response(
|
|
42
|
+
{
|
|
43
|
+
"cable_id": cable_id,
|
|
44
|
+
"segment_count": len(segments),
|
|
45
|
+
"total_length": total_length,
|
|
46
|
+
"segments": segments,
|
|
47
|
+
}
|
|
48
|
+
)
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
from django.urls import path
|
|
2
|
+
from netbox.api.routers import NetBoxRouter
|
|
3
|
+
|
|
4
|
+
from . import views
|
|
5
|
+
from .external_geo import ExternalLayerGeoView
|
|
6
|
+
from .geo import (
|
|
7
|
+
AerialSpanGeoViewSet,
|
|
8
|
+
CircuitGeoViewSet,
|
|
9
|
+
ConduitBankGeoViewSet,
|
|
10
|
+
ConduitGeoViewSet,
|
|
11
|
+
DirectBuriedGeoViewSet,
|
|
12
|
+
PathwayGeoViewSet,
|
|
13
|
+
StructureGeoViewSet,
|
|
14
|
+
)
|
|
15
|
+
from .traversal import CableTraceView
|
|
16
|
+
|
|
17
|
+
router = NetBoxRouter()
|
|
18
|
+
router.register("structures", views.StructureViewSet)
|
|
19
|
+
router.register("conduit-banks", views.ConduitBankViewSet)
|
|
20
|
+
router.register("pathways", views.PathwayViewSet)
|
|
21
|
+
router.register("conduits", views.ConduitViewSet)
|
|
22
|
+
router.register("aerial-spans", views.AerialSpanViewSet)
|
|
23
|
+
router.register("direct-buried", views.DirectBuriedViewSet)
|
|
24
|
+
router.register("innerducts", views.InnerductViewSet)
|
|
25
|
+
router.register("junctions", views.ConduitJunctionViewSet)
|
|
26
|
+
router.register("pathway-locations", views.PathwayLocationViewSet)
|
|
27
|
+
router.register("cable-segments", views.CableSegmentViewSet)
|
|
28
|
+
router.register("site-geometries", views.SiteGeometryViewSet)
|
|
29
|
+
router.register("circuit-geometries", views.CircuitGeometryViewSet)
|
|
30
|
+
router.register("planned-routes", views.PlannedRouteViewSet)
|
|
31
|
+
|
|
32
|
+
# GeoJSON endpoints for QGIS / GIS client consumption
|
|
33
|
+
router.register("geo/structures", StructureGeoViewSet, basename="geo-structure")
|
|
34
|
+
router.register("geo/pathways", PathwayGeoViewSet, basename="geo-pathway")
|
|
35
|
+
router.register("geo/conduit-banks", ConduitBankGeoViewSet, basename="geo-conduitbank")
|
|
36
|
+
router.register("geo/conduits", ConduitGeoViewSet, basename="geo-conduit")
|
|
37
|
+
router.register("geo/aerial-spans", AerialSpanGeoViewSet, basename="geo-aerialspan")
|
|
38
|
+
router.register("geo/direct-buried", DirectBuriedGeoViewSet, basename="geo-directburied")
|
|
39
|
+
router.register("geo/circuits", CircuitGeoViewSet, basename="geo-circuit")
|
|
40
|
+
|
|
41
|
+
urlpatterns = router.urls + [
|
|
42
|
+
# External plugin map layer endpoint
|
|
43
|
+
path("geo/external/<str:layer_name>/", ExternalLayerGeoView.as_view(), name="external-geo"),
|
|
44
|
+
# Graph traversal endpoints
|
|
45
|
+
path("traversal/cable-trace/", CableTraceView.as_view(), name="traversal-cable-trace"),
|
|
46
|
+
]
|