netbox-cesnet-services-plugin 3.0.1__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_cesnet_services_plugin/__init__.py +27 -0
- netbox_cesnet_services_plugin/api/__init__.py +0 -0
- netbox_cesnet_services_plugin/api/serializers.py +226 -0
- netbox_cesnet_services_plugin/api/urls.py +14 -0
- netbox_cesnet_services_plugin/api/views.py +64 -0
- netbox_cesnet_services_plugin/choices.py +57 -0
- netbox_cesnet_services_plugin/filtersets/__init__.py +17 -0
- netbox_cesnet_services_plugin/filtersets/bgpconnection.py +144 -0
- netbox_cesnet_services_plugin/filtersets/bgpconnection_aggregation.py +68 -0
- netbox_cesnet_services_plugin/filtersets/lldpneighbor.py +71 -0
- netbox_cesnet_services_plugin/filtersets/lldpneighborleaf.py +34 -0
- netbox_cesnet_services_plugin/filtersets/service_core_link.py +94 -0
- netbox_cesnet_services_plugin/filtersets/service_core_trunk.py +70 -0
- netbox_cesnet_services_plugin/filtersets/service_ip.py +71 -0
- netbox_cesnet_services_plugin/forms/__init__.py +53 -0
- netbox_cesnet_services_plugin/forms/bgpconnection.py +215 -0
- netbox_cesnet_services_plugin/forms/bgpconnection_aggregation.py +74 -0
- netbox_cesnet_services_plugin/forms/lldpneighbor.py +160 -0
- netbox_cesnet_services_plugin/forms/lldpneighborleaf.py +120 -0
- netbox_cesnet_services_plugin/forms/service_core_link.py +202 -0
- netbox_cesnet_services_plugin/forms/service_core_trunk.py +132 -0
- netbox_cesnet_services_plugin/forms/service_ip.py +160 -0
- netbox_cesnet_services_plugin/graphql/__init__.py +3 -0
- netbox_cesnet_services_plugin/graphql/filters.py +68 -0
- netbox_cesnet_services_plugin/graphql/schema.py +34 -0
- netbox_cesnet_services_plugin/graphql/types.py +164 -0
- netbox_cesnet_services_plugin/migrations/0001_initial.py +71 -0
- netbox_cesnet_services_plugin/migrations/0002_bgpconnection_comments.py +17 -0
- netbox_cesnet_services_plugin/migrations/0003_alter_bgpconnection_options_bgpconnection_device.py +26 -0
- netbox_cesnet_services_plugin/migrations/0004_alter_bgpconnection_options_bgpconnection_raw_vrf_and_more.py +43 -0
- netbox_cesnet_services_plugin/migrations/0005_alter_bgpconnection_role.py +20 -0
- netbox_cesnet_services_plugin/migrations/0006_lldpneighbor.py +85 -0
- netbox_cesnet_services_plugin/migrations/0007_lldpneighbor_comments.py +17 -0
- netbox_cesnet_services_plugin/migrations/0008_alter_lldpneighbor_device_a_and_more.py +113 -0
- netbox_cesnet_services_plugin/migrations/0009_lldpneighbor_status_lldpneighborleaf_status.py +22 -0
- netbox_cesnet_services_plugin/migrations/0010_alter_bgpconnection_raw_vrf_and_more.py +25 -0
- netbox_cesnet_services_plugin/migrations/0011_lldpneighbor_last_seen_lldpneighbor_status_detail.py +22 -0
- netbox_cesnet_services_plugin/migrations/0012_alter_lldpneighbor_last_seen.py +20 -0
- netbox_cesnet_services_plugin/migrations/0013_bgpconnection_last_seen.py +17 -0
- netbox_cesnet_services_plugin/migrations/0014_servicecoretrunk_servicecorelink_serviceip.py +135 -0
- netbox_cesnet_services_plugin/migrations/0015_alter_service_status_to_circuit_choices.py +59 -0
- netbox_cesnet_services_plugin/migrations/__init__.py +0 -0
- netbox_cesnet_services_plugin/models/__init__.py +6 -0
- netbox_cesnet_services_plugin/models/bgpconnection.py +158 -0
- netbox_cesnet_services_plugin/models/cesnet_service_base.py +59 -0
- netbox_cesnet_services_plugin/models/lldpneighbor.py +162 -0
- netbox_cesnet_services_plugin/models/lldpneighborleaf.py +96 -0
- netbox_cesnet_services_plugin/models/service_core_link.py +170 -0
- netbox_cesnet_services_plugin/models/service_core_trunk.py +61 -0
- netbox_cesnet_services_plugin/models/service_ip.py +121 -0
- netbox_cesnet_services_plugin/navigation.py +58 -0
- netbox_cesnet_services_plugin/tables/__init__.py +17 -0
- netbox_cesnet_services_plugin/tables/bgpconnection.py +86 -0
- netbox_cesnet_services_plugin/tables/bgpconnection_aggregation.py +78 -0
- netbox_cesnet_services_plugin/tables/lldpneighbor.py +44 -0
- netbox_cesnet_services_plugin/tables/lldpneighborleaf.py +38 -0
- netbox_cesnet_services_plugin/tables/service_core_link.py +39 -0
- netbox_cesnet_services_plugin/tables/service_core_trunk.py +30 -0
- netbox_cesnet_services_plugin/tables/service_ip.py +31 -0
- netbox_cesnet_services_plugin/template_content.py +330 -0
- netbox_cesnet_services_plugin/templates/netbox_cesnet_services_plugin/bgpconnection/bgpconnection.html +83 -0
- netbox_cesnet_services_plugin/templates/netbox_cesnet_services_plugin/bgpconnection/bgpconnection_aggregation_list.html +12 -0
- netbox_cesnet_services_plugin/templates/netbox_cesnet_services_plugin/bgpconnection/bgpconnection_include.html +5 -0
- netbox_cesnet_services_plugin/templates/netbox_cesnet_services_plugin/bgpconnection.html +4 -0
- netbox_cesnet_services_plugin/templates/netbox_cesnet_services_plugin/details/connection_endpoints.html +37 -0
- netbox_cesnet_services_plugin/templates/netbox_cesnet_services_plugin/details/detail_interface_inc.html +66 -0
- netbox_cesnet_services_plugin/templates/netbox_cesnet_services_plugin/details/multiple_children.html +90 -0
- netbox_cesnet_services_plugin/templates/netbox_cesnet_services_plugin/lldpneighbor/lldpneighbor.html +76 -0
- netbox_cesnet_services_plugin/templates/netbox_cesnet_services_plugin/lldpneighbor/lldpneighbor_include.html +5 -0
- netbox_cesnet_services_plugin/templates/netbox_cesnet_services_plugin/lldpneighbor.html +4 -0
- netbox_cesnet_services_plugin/templates/netbox_cesnet_services_plugin/lldpneighborleaf/lldpneighborleaf.html +66 -0
- netbox_cesnet_services_plugin/templates/netbox_cesnet_services_plugin/lldpneighborleaf/lldpneighborleaf_include.html +5 -0
- netbox_cesnet_services_plugin/templates/netbox_cesnet_services_plugin/lldpneighborleaf.html +4 -0
- netbox_cesnet_services_plugin/templates/netbox_cesnet_services_plugin/servicecorelink/servicecorelink.html +205 -0
- netbox_cesnet_services_plugin/templates/netbox_cesnet_services_plugin/servicecorelink.html +2 -0
- netbox_cesnet_services_plugin/templates/netbox_cesnet_services_plugin/servicecoretrunk/servicecoretrunk.html +97 -0
- netbox_cesnet_services_plugin/templates/netbox_cesnet_services_plugin/servicecoretrunk.html +2 -0
- netbox_cesnet_services_plugin/templates/netbox_cesnet_services_plugin/serviceip/serviceip.html +152 -0
- netbox_cesnet_services_plugin/templates/netbox_cesnet_services_plugin/serviceip.html +2 -0
- netbox_cesnet_services_plugin/tests/__init__.py +0 -0
- netbox_cesnet_services_plugin/tests/test_service_core_link.py +294 -0
- netbox_cesnet_services_plugin/tests/test_service_core_trunk.py +268 -0
- netbox_cesnet_services_plugin/tests/test_service_ip.py +341 -0
- netbox_cesnet_services_plugin/urls.py +224 -0
- netbox_cesnet_services_plugin/views/__init__.py +71 -0
- netbox_cesnet_services_plugin/views/bgpconnection.py +76 -0
- netbox_cesnet_services_plugin/views/bgpconnection_aggregation.py +48 -0
- netbox_cesnet_services_plugin/views/lldpneighbor.py +43 -0
- netbox_cesnet_services_plugin/views/lldpneighborleaf.py +49 -0
- netbox_cesnet_services_plugin/views/service_core_link.py +49 -0
- netbox_cesnet_services_plugin/views/service_core_trunk.py +46 -0
- netbox_cesnet_services_plugin/views/service_ip.py +50 -0
- netbox_cesnet_services_plugin-3.0.1.dist-info/METADATA +135 -0
- netbox_cesnet_services_plugin-3.0.1.dist-info/RECORD +97 -0
- netbox_cesnet_services_plugin-3.0.1.dist-info/WHEEL +5 -0
- netbox_cesnet_services_plugin-3.0.1.dist-info/licenses/LICENSE +22 -0
- netbox_cesnet_services_plugin-3.0.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""Top-level package for NetBox cesnet_services Plugin."""
|
|
2
|
+
|
|
3
|
+
__author__ = """Jan Krupa"""
|
|
4
|
+
__email__ = "jan.krupa@cesnet.cz"
|
|
5
|
+
__version__ = "3.0.1"
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
from netbox.plugins import PluginConfig
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class CesnetServicesConfig(PluginConfig):
|
|
12
|
+
name = "netbox_cesnet_services_plugin"
|
|
13
|
+
verbose_name = "NetBox cesnet_services Plugin"
|
|
14
|
+
description = "NetBox plugin for CESNET services."
|
|
15
|
+
version = __version__
|
|
16
|
+
base_url = "netbox-cesnet-services-plugin"
|
|
17
|
+
author = __author__
|
|
18
|
+
author_email = __email__
|
|
19
|
+
min_version = "4.5.4"
|
|
20
|
+
max_version = "4.6.99"
|
|
21
|
+
default_settings = {
|
|
22
|
+
"bgp_last_seen_warning_days": 2,
|
|
23
|
+
"bgp_last_seen_danger_days": 5,
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
config = CesnetServicesConfig
|
|
File without changes
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
from dcim.api.serializers import DeviceSerializer, InterfaceSerializer
|
|
2
|
+
from ipam.api.serializers import ASNSerializer, IPAddressSerializer, PrefixSerializer, VRFSerializer
|
|
3
|
+
from netbox.api.serializers import NetBoxModelSerializer
|
|
4
|
+
from rest_framework import serializers
|
|
5
|
+
from tenancy.api.serializers import TenantSerializer
|
|
6
|
+
|
|
7
|
+
from netbox_cesnet_services_plugin.models import (
|
|
8
|
+
BGPConnection,
|
|
9
|
+
LLDPNeighbor,
|
|
10
|
+
LLDPNeighborLeaf,
|
|
11
|
+
ServiceCoreTrunk,
|
|
12
|
+
ServiceCoreLink,
|
|
13
|
+
ServiceIP,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class LLDPNeighborLeafSerializer(NetBoxModelSerializer):
|
|
18
|
+
url = serializers.HyperlinkedIdentityField(
|
|
19
|
+
view_name="plugins-api:netbox_cesnet_services_plugin-api:lldpneighborleaf-detail"
|
|
20
|
+
)
|
|
21
|
+
device_nb = DeviceSerializer(nested=True)
|
|
22
|
+
interface_nb = InterfaceSerializer(nested=True)
|
|
23
|
+
|
|
24
|
+
class Meta:
|
|
25
|
+
model = LLDPNeighborLeaf
|
|
26
|
+
fields = (
|
|
27
|
+
"id",
|
|
28
|
+
"url",
|
|
29
|
+
"device_nb",
|
|
30
|
+
"interface_nb",
|
|
31
|
+
"device_ext",
|
|
32
|
+
"interface_ext",
|
|
33
|
+
"status",
|
|
34
|
+
"comments",
|
|
35
|
+
"tags",
|
|
36
|
+
"imported_data",
|
|
37
|
+
"custom_fields",
|
|
38
|
+
"created",
|
|
39
|
+
"last_updated",
|
|
40
|
+
)
|
|
41
|
+
brief_fields = (
|
|
42
|
+
"id",
|
|
43
|
+
"device_nb",
|
|
44
|
+
"interface_nb",
|
|
45
|
+
"device_ext",
|
|
46
|
+
"interface_ext",
|
|
47
|
+
"status",
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class LLDPNeighborSerializer(NetBoxModelSerializer):
|
|
52
|
+
url = serializers.HyperlinkedIdentityField(
|
|
53
|
+
view_name="plugins-api:netbox_cesnet_services_plugin-api:lldpneighbor-detail"
|
|
54
|
+
)
|
|
55
|
+
device_a = DeviceSerializer(nested=True)
|
|
56
|
+
interface_a = InterfaceSerializer(nested=True)
|
|
57
|
+
device_b = DeviceSerializer(nested=True)
|
|
58
|
+
interface_b = InterfaceSerializer(nested=True)
|
|
59
|
+
|
|
60
|
+
class Meta:
|
|
61
|
+
model = LLDPNeighbor
|
|
62
|
+
fields = (
|
|
63
|
+
"id",
|
|
64
|
+
"url",
|
|
65
|
+
"device_a",
|
|
66
|
+
"interface_a",
|
|
67
|
+
"device_b",
|
|
68
|
+
"interface_b",
|
|
69
|
+
"status",
|
|
70
|
+
"status_detail",
|
|
71
|
+
"last_seen",
|
|
72
|
+
"comments",
|
|
73
|
+
"tags",
|
|
74
|
+
"imported_data",
|
|
75
|
+
"custom_fields",
|
|
76
|
+
"created",
|
|
77
|
+
"last_updated",
|
|
78
|
+
)
|
|
79
|
+
brief_fields = (
|
|
80
|
+
"id",
|
|
81
|
+
"device_a",
|
|
82
|
+
"interface_a",
|
|
83
|
+
"device_b",
|
|
84
|
+
"interface_b",
|
|
85
|
+
"status",
|
|
86
|
+
"status_detail",
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
class ServiceCoreTrunkSerializer(NetBoxModelSerializer):
|
|
91
|
+
url = serializers.HyperlinkedIdentityField(
|
|
92
|
+
view_name="plugins-api:netbox_cesnet_services_plugin-api:servicecoretrunk-detail"
|
|
93
|
+
)
|
|
94
|
+
tenant = TenantSerializer(nested=True, allow_null=True, required=False)
|
|
95
|
+
node_a = DeviceSerializer(nested=True, allow_null=True, required=False)
|
|
96
|
+
node_b = DeviceSerializer(nested=True, allow_null=True, required=False)
|
|
97
|
+
if_a = InterfaceSerializer(nested=True, allow_null=True, required=False)
|
|
98
|
+
if_b = InterfaceSerializer(nested=True, allow_null=True, required=False)
|
|
99
|
+
|
|
100
|
+
class Meta:
|
|
101
|
+
model = ServiceCoreTrunk
|
|
102
|
+
fields = (
|
|
103
|
+
"id", "display", "url",
|
|
104
|
+
"name", "status", "active", "tenant",
|
|
105
|
+
"service_start", "service_end", "rt", "monitored",
|
|
106
|
+
"node_a", "node_b", "if_a", "if_b",
|
|
107
|
+
"linked_segments",
|
|
108
|
+
"tags", "comments", "custom_fields", "created", "last_updated",
|
|
109
|
+
)
|
|
110
|
+
brief_fields = (
|
|
111
|
+
"id", "url", "display", "name", "status", "tenant",
|
|
112
|
+
"node_a", "node_b",
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
class ServiceCoreLinkSerializer(NetBoxModelSerializer):
|
|
117
|
+
url = serializers.HyperlinkedIdentityField(
|
|
118
|
+
view_name="plugins-api:netbox_cesnet_services_plugin-api:servicecorelink-detail"
|
|
119
|
+
)
|
|
120
|
+
tenant = TenantSerializer(nested=True, allow_null=True, required=False)
|
|
121
|
+
node_a = DeviceSerializer(nested=True, allow_null=True, required=False)
|
|
122
|
+
node_b = DeviceSerializer(nested=True, allow_null=True, required=False)
|
|
123
|
+
phy_if_a = InterfaceSerializer(nested=True, allow_null=True, required=False)
|
|
124
|
+
phy_if_b = InterfaceSerializer(nested=True, allow_null=True, required=False)
|
|
125
|
+
ipv4_addr_a = IPAddressSerializer(nested=True, allow_null=True, required=False)
|
|
126
|
+
ipv4_addr_b = IPAddressSerializer(nested=True, allow_null=True, required=False)
|
|
127
|
+
ipv6_addr_a = IPAddressSerializer(nested=True, allow_null=True, required=False)
|
|
128
|
+
ipv6_addr_b = IPAddressSerializer(nested=True, allow_null=True, required=False)
|
|
129
|
+
|
|
130
|
+
class Meta:
|
|
131
|
+
model = ServiceCoreLink
|
|
132
|
+
fields = (
|
|
133
|
+
"id", "display", "url",
|
|
134
|
+
"name", "status", "active", "tenant",
|
|
135
|
+
"service_start", "service_end", "rt", "monitored",
|
|
136
|
+
"node_a", "node_b", "phy_if_a", "phy_if_b",
|
|
137
|
+
"linked_segments", "saps", "core_trunks",
|
|
138
|
+
"lldp_enable", "flowspec_enable",
|
|
139
|
+
"encapsulation_mode", "encapsulation_qinq_s_vlan_id", "encapsulation_qinq_c_vlan_id",
|
|
140
|
+
"routing_isis_enabled", "routing_isis_instance", "routing_isis_bfd",
|
|
141
|
+
"routing_ospf_enable", "routing_ospf_area",
|
|
142
|
+
"ipv4_addr_a", "ipv4_addr_b", "ipv6_addr_a", "ipv6_addr_b",
|
|
143
|
+
"tags", "comments", "custom_fields", "created", "last_updated",
|
|
144
|
+
)
|
|
145
|
+
brief_fields = (
|
|
146
|
+
"id", "url", "display", "name", "status", "tenant",
|
|
147
|
+
"node_a", "node_b", "encapsulation_mode",
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
class ServiceIPSerializer(NetBoxModelSerializer):
|
|
152
|
+
url = serializers.HyperlinkedIdentityField(
|
|
153
|
+
view_name="plugins-api:netbox_cesnet_services_plugin-api:serviceip-detail"
|
|
154
|
+
)
|
|
155
|
+
tenant = TenantSerializer(nested=True, allow_null=True, required=False)
|
|
156
|
+
sap = InterfaceSerializer(nested=True, allow_null=True, required=False)
|
|
157
|
+
ipv4_addr = IPAddressSerializer(nested=True, allow_null=True, required=False)
|
|
158
|
+
ipv6_addr = IPAddressSerializer(nested=True, allow_null=True, required=False)
|
|
159
|
+
routing_static_next_hop = IPAddressSerializer(nested=True, allow_null=True, required=False)
|
|
160
|
+
routing_bgp_peer_as = ASNSerializer(nested=True, allow_null=True, required=False)
|
|
161
|
+
routing_bgp_peer_ip = IPAddressSerializer(nested=True, allow_null=True, required=False)
|
|
162
|
+
|
|
163
|
+
class Meta:
|
|
164
|
+
model = ServiceIP
|
|
165
|
+
fields = (
|
|
166
|
+
"id", "display", "url",
|
|
167
|
+
"name", "status", "active", "tenant",
|
|
168
|
+
"service_start", "service_end", "rt", "monitored",
|
|
169
|
+
"sap",
|
|
170
|
+
"encapsulation_mode", "encapsulation_qinq_s_vlan_id", "encapsulation_qinq_c_vlan_id",
|
|
171
|
+
"ipv4_addr", "ipv6_addr",
|
|
172
|
+
"routing_type", "routing_prefixes",
|
|
173
|
+
"routing_static_next_hop",
|
|
174
|
+
"routing_bgp_peer_as", "routing_bgp_peer_ip", "routing_bgp_policy",
|
|
175
|
+
"tags", "comments", "custom_fields", "created", "last_updated",
|
|
176
|
+
)
|
|
177
|
+
brief_fields = (
|
|
178
|
+
"id", "url", "display", "name", "status", "tenant",
|
|
179
|
+
"sap", "routing_type",
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
class BGPConnectionSerializer(NetBoxModelSerializer):
|
|
184
|
+
url = serializers.HyperlinkedIdentityField(
|
|
185
|
+
view_name="plugins-api:netbox_cesnet_services_plugin-api:bgpconnection-detail"
|
|
186
|
+
)
|
|
187
|
+
device = DeviceSerializer(nested=True)
|
|
188
|
+
next_hop = IPAddressSerializer(nested=True, allow_null=True)
|
|
189
|
+
bgp_prefix = PrefixSerializer(nested=True, allow_null=True)
|
|
190
|
+
vrf = VRFSerializer(nested=True, allow_null=True)
|
|
191
|
+
|
|
192
|
+
class Meta:
|
|
193
|
+
model = BGPConnection
|
|
194
|
+
fields = (
|
|
195
|
+
"id",
|
|
196
|
+
"display",
|
|
197
|
+
"url",
|
|
198
|
+
"device",
|
|
199
|
+
"raw_next_hop",
|
|
200
|
+
"next_hop",
|
|
201
|
+
"raw_bgp_prefix",
|
|
202
|
+
"bgp_prefix",
|
|
203
|
+
"raw_vrf",
|
|
204
|
+
"vrf",
|
|
205
|
+
"role",
|
|
206
|
+
"last_seen",
|
|
207
|
+
"tags",
|
|
208
|
+
"import_data",
|
|
209
|
+
"custom_fields",
|
|
210
|
+
"created",
|
|
211
|
+
"last_updated",
|
|
212
|
+
)
|
|
213
|
+
brief_fields = (
|
|
214
|
+
"id",
|
|
215
|
+
"url",
|
|
216
|
+
"display",
|
|
217
|
+
"device",
|
|
218
|
+
"raw_next_hop",
|
|
219
|
+
"next_hop",
|
|
220
|
+
"raw_bgp_prefix",
|
|
221
|
+
"bgp_prefix",
|
|
222
|
+
"raw_vrf",
|
|
223
|
+
"vrf",
|
|
224
|
+
"role",
|
|
225
|
+
"tags",
|
|
226
|
+
)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from netbox.api.routers import NetBoxRouter
|
|
2
|
+
|
|
3
|
+
from . import views
|
|
4
|
+
|
|
5
|
+
app_name = "netbox_cesnet_services_plugin"
|
|
6
|
+
router = NetBoxRouter()
|
|
7
|
+
router.register("bgp-connections", views.BGPConnectionViewSet)
|
|
8
|
+
router.register("lldp-neighbors", views.LLDPNeighborViewSet)
|
|
9
|
+
router.register("lldp-neighbor-leafs", views.LLDPNeighborLeafViewSet)
|
|
10
|
+
router.register("service-core-trunks", views.ServiceCoreTrunkViewSet)
|
|
11
|
+
router.register("service-core-links", views.ServiceCoreLinkViewSet)
|
|
12
|
+
router.register("service-ip", views.ServiceIPViewSet)
|
|
13
|
+
|
|
14
|
+
urlpatterns = router.urls
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
from netbox.api.metadata import ContentTypeMetadata
|
|
2
|
+
from netbox.api.viewsets import NetBoxModelViewSet
|
|
3
|
+
|
|
4
|
+
from netbox_cesnet_services_plugin import filtersets, models
|
|
5
|
+
from .serializers import (
|
|
6
|
+
BGPConnectionSerializer,
|
|
7
|
+
LLDPNeighborSerializer,
|
|
8
|
+
LLDPNeighborLeafSerializer,
|
|
9
|
+
ServiceCoreTrunkSerializer,
|
|
10
|
+
ServiceCoreLinkSerializer,
|
|
11
|
+
ServiceIPSerializer,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class BGPConnectionViewSet(NetBoxModelViewSet):
|
|
16
|
+
metadata_class = ContentTypeMetadata
|
|
17
|
+
queryset = models.BGPConnection.objects.all()
|
|
18
|
+
serializer_class = BGPConnectionSerializer
|
|
19
|
+
filterset_class = filtersets.BGPConnectionFilterSet
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class LLDPNeighborViewSet(NetBoxModelViewSet):
|
|
23
|
+
metadata_class = ContentTypeMetadata
|
|
24
|
+
queryset = models.LLDPNeighbor.objects.all()
|
|
25
|
+
serializer_class = LLDPNeighborSerializer
|
|
26
|
+
filterset_class = filtersets.LLDPNeighborFilterSet
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class LLDPNeighborLeafViewSet(NetBoxModelViewSet):
|
|
30
|
+
metadata_class = ContentTypeMetadata
|
|
31
|
+
queryset = models.LLDPNeighborLeaf.objects.all()
|
|
32
|
+
serializer_class = LLDPNeighborLeafSerializer
|
|
33
|
+
filterset_class = filtersets.LLDPNeighborLeafFilterSet
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class ServiceCoreTrunkViewSet(NetBoxModelViewSet):
|
|
37
|
+
metadata_class = ContentTypeMetadata
|
|
38
|
+
queryset = models.ServiceCoreTrunk.objects.select_related(
|
|
39
|
+
"tenant", "node_a", "node_b", "if_a", "if_b"
|
|
40
|
+
)
|
|
41
|
+
serializer_class = ServiceCoreTrunkSerializer
|
|
42
|
+
filterset_class = filtersets.ServiceCoreTrunkFilterSet
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class ServiceCoreLinkViewSet(NetBoxModelViewSet):
|
|
46
|
+
metadata_class = ContentTypeMetadata
|
|
47
|
+
queryset = models.ServiceCoreLink.objects.select_related(
|
|
48
|
+
"tenant", "node_a", "node_b", "phy_if_a", "phy_if_b",
|
|
49
|
+
"ipv4_addr_a", "ipv4_addr_b", "ipv6_addr_a", "ipv6_addr_b",
|
|
50
|
+
).prefetch_related("saps", "core_trunks", "linked_segments")
|
|
51
|
+
serializer_class = ServiceCoreLinkSerializer
|
|
52
|
+
filterset_class = filtersets.ServiceCoreLinkFilterSet
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class ServiceIPViewSet(NetBoxModelViewSet):
|
|
57
|
+
metadata_class = ContentTypeMetadata
|
|
58
|
+
queryset = models.ServiceIP.objects.select_related(
|
|
59
|
+
"tenant", "sap",
|
|
60
|
+
"ipv4_addr", "ipv6_addr",
|
|
61
|
+
"routing_static_next_hop", "routing_bgp_peer_as", "routing_bgp_peer_ip",
|
|
62
|
+
).prefetch_related("routing_prefixes")
|
|
63
|
+
serializer_class = ServiceIPSerializer
|
|
64
|
+
filterset_class = filtersets.ServiceIPFilterSet
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
from utilities.choices import ChoiceSet
|
|
2
|
+
from django.utils.translation import gettext_lazy as _
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class EncapsulationModeChoices(ChoiceSet):
|
|
6
|
+
MODE_NONE = "none"
|
|
7
|
+
MODE_DOT1Q = "dot1q"
|
|
8
|
+
MODE_QINQ = "qinq"
|
|
9
|
+
|
|
10
|
+
CHOICES = [
|
|
11
|
+
(MODE_NONE, _("None / Untagged"), "gray"),
|
|
12
|
+
(MODE_DOT1Q, _("dot1q"), "blue"),
|
|
13
|
+
(MODE_QINQ, _("QinQ"), "purple"),
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class RoutingTypeChoices(ChoiceSet):
|
|
18
|
+
TYPE_NONE = "none"
|
|
19
|
+
TYPE_STATIC = "static"
|
|
20
|
+
TYPE_BGP = "bgp"
|
|
21
|
+
|
|
22
|
+
CHOICES = [
|
|
23
|
+
(TYPE_NONE, _("None"), "gray"),
|
|
24
|
+
(TYPE_STATIC, _("Static"), "blue"),
|
|
25
|
+
(TYPE_BGP, _("BGP"), "green"),
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class LLDPNeigborStatusChoices(ChoiceSet):
|
|
30
|
+
STATUS_ACTIVE = "active"
|
|
31
|
+
STATUS_INACTIVE = "inactive"
|
|
32
|
+
|
|
33
|
+
CHOICES = (
|
|
34
|
+
(STATUS_ACTIVE, _("Active"), "green"),
|
|
35
|
+
(STATUS_INACTIVE, _("Inactive"), "gray"),
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class LLDPNeigborStatusDetailChoices(ChoiceSet):
|
|
40
|
+
"""
|
|
41
|
+
Fully connected - both sides found in LLDP data
|
|
42
|
+
Lost Sync - previous state was fully connected, but one side is not in LLDP data -> after N days switch to unconfirmed or inactive
|
|
43
|
+
Unconfirmed - one side is not in LLDP data, but the other side is. Both sides are in the Netbox.
|
|
44
|
+
None - no detail needed, primary status is inactive. No side is in LLDP data.
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
STATUS_ACTIVE = "fully_connected"
|
|
48
|
+
STATUS_UNCONFIRMED = "unconfirmed"
|
|
49
|
+
STATUS_ONEWAY = "lost_sync"
|
|
50
|
+
STATUS_NONE = "none"
|
|
51
|
+
|
|
52
|
+
CHOICES = (
|
|
53
|
+
(STATUS_ACTIVE, _("Fully Connected"), "green"),
|
|
54
|
+
(STATUS_UNCONFIRMED, _("Unconfirmed"), "yellow"),
|
|
55
|
+
(STATUS_ONEWAY, _("Lost Sync"), "orange"),
|
|
56
|
+
(STATUS_NONE, _("None"), "gray"),
|
|
57
|
+
)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from .bgpconnection import BGPConnectionFilterSet
|
|
2
|
+
from .bgpconnection_aggregation import BGPConnectionAggregationFilterSet
|
|
3
|
+
from .lldpneighbor import LLDPNeighborFilterSet
|
|
4
|
+
from .lldpneighborleaf import LLDPNeighborLeafFilterSet
|
|
5
|
+
from .service_core_trunk import ServiceCoreTrunkFilterSet
|
|
6
|
+
from .service_core_link import ServiceCoreLinkFilterSet
|
|
7
|
+
from .service_ip import ServiceIPFilterSet
|
|
8
|
+
|
|
9
|
+
__all__ = [
|
|
10
|
+
"BGPConnectionFilterSet",
|
|
11
|
+
"BGPConnectionAggregationFilterSet",
|
|
12
|
+
"LLDPNeighborFilterSet",
|
|
13
|
+
"LLDPNeighborLeafFilterSet",
|
|
14
|
+
"ServiceCoreTrunkFilterSet",
|
|
15
|
+
"ServiceCoreLinkFilterSet",
|
|
16
|
+
"ServiceIPFilterSet",
|
|
17
|
+
]
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import django_filters
|
|
2
|
+
from dcim.models import Device, Interface
|
|
3
|
+
from django.db.models import Q
|
|
4
|
+
from django.utils.translation import gettext as _
|
|
5
|
+
from extras.filters import TagFilter
|
|
6
|
+
from ipam.models import VRF, IPAddress, Prefix
|
|
7
|
+
from netbox.filtersets import NetBoxModelFilterSet
|
|
8
|
+
from tenancy.models import Tenant
|
|
9
|
+
from utilities.forms.fields import DynamicMultipleChoiceField
|
|
10
|
+
|
|
11
|
+
from netbox_cesnet_services_plugin.models import BGPConnection, BGPConnectionChoices
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class BGPConnectionFilterSet(NetBoxModelFilterSet):
|
|
15
|
+
q = django_filters.CharFilter(method="search", label="Search")
|
|
16
|
+
device = django_filters.ModelMultipleChoiceFilter(queryset=Device.objects.all())
|
|
17
|
+
device_id = django_filters.ModelMultipleChoiceFilter(
|
|
18
|
+
field_name="device__id",
|
|
19
|
+
queryset=Device.objects.all(),
|
|
20
|
+
to_field_name="id",
|
|
21
|
+
label="Device (ID)",
|
|
22
|
+
)
|
|
23
|
+
next_hop = django_filters.ModelMultipleChoiceFilter(
|
|
24
|
+
queryset=IPAddress.objects.all()
|
|
25
|
+
)
|
|
26
|
+
next_hop_id = django_filters.ModelMultipleChoiceFilter(
|
|
27
|
+
field_name="next_hop__id",
|
|
28
|
+
queryset=IPAddress.objects.all(),
|
|
29
|
+
to_field_name="id",
|
|
30
|
+
label="Next Hop (ID)",
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
next_hop_interface_id = django_filters.ModelMultipleChoiceFilter(
|
|
34
|
+
field_name="next_hop__interface__id",
|
|
35
|
+
queryset=Interface.objects.all(),
|
|
36
|
+
to_field_name="id",
|
|
37
|
+
label="Next Hop Interface (ID)",
|
|
38
|
+
)
|
|
39
|
+
bgp_prefix = django_filters.ModelMultipleChoiceFilter(queryset=Prefix.objects.all())
|
|
40
|
+
bgp_prefix_id = django_filters.ModelMultipleChoiceFilter(
|
|
41
|
+
field_name="bgp_prefix__id",
|
|
42
|
+
queryset=Prefix.objects.all(),
|
|
43
|
+
to_field_name="id",
|
|
44
|
+
label="BGP Prefix (ID)",
|
|
45
|
+
)
|
|
46
|
+
bgp_prefix_tenant_id = django_filters.ModelMultipleChoiceFilter(
|
|
47
|
+
field_name="bgp_prefix__tenant__id",
|
|
48
|
+
queryset=Tenant.objects.all(),
|
|
49
|
+
to_field_name="id",
|
|
50
|
+
label="BGP Prefix Tenant (ID)",
|
|
51
|
+
)
|
|
52
|
+
vrf = django_filters.ModelMultipleChoiceFilter(queryset=VRF.objects.all())
|
|
53
|
+
vrf_id = django_filters.ModelMultipleChoiceFilter(
|
|
54
|
+
field_name="vrf__id",
|
|
55
|
+
queryset=VRF.objects.all(),
|
|
56
|
+
to_field_name="id",
|
|
57
|
+
label="VRF (ID)",
|
|
58
|
+
)
|
|
59
|
+
vrf_none = django_filters.BooleanFilter(method="_vrf_none", label="Empty VRF")
|
|
60
|
+
|
|
61
|
+
# TODO: as CHAR filter or as IPAddress filter?
|
|
62
|
+
raw_next_hop = django_filters.CharFilter(
|
|
63
|
+
# method='filter_address',
|
|
64
|
+
label=_("Address"),
|
|
65
|
+
)
|
|
66
|
+
raw_bgp_prefix = django_filters.CharFilter(
|
|
67
|
+
# method='filter_prefix',
|
|
68
|
+
label=_("Prefix"),
|
|
69
|
+
)
|
|
70
|
+
raw_vrf = django_filters.CharFilter(
|
|
71
|
+
label=_("VRF"),
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
role = DynamicMultipleChoiceField(choices=BGPConnectionChoices, required=False)
|
|
75
|
+
|
|
76
|
+
last_seen = django_filters.DateTimeFilter()
|
|
77
|
+
last_seen__gte = django_filters.DateTimeFilter(
|
|
78
|
+
field_name="last_seen", lookup_expr="gte"
|
|
79
|
+
)
|
|
80
|
+
last_seen__lte = django_filters.DateTimeFilter(
|
|
81
|
+
field_name="last_seen", lookup_expr="lte"
|
|
82
|
+
)
|
|
83
|
+
last_seen__isnull = django_filters.BooleanFilter(
|
|
84
|
+
field_name="last_seen", lookup_expr="isnull"
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
tag = TagFilter()
|
|
88
|
+
|
|
89
|
+
class Meta:
|
|
90
|
+
model = BGPConnection
|
|
91
|
+
fields = [
|
|
92
|
+
"raw_next_hop",
|
|
93
|
+
"next_hop",
|
|
94
|
+
"bgp_prefix",
|
|
95
|
+
"raw_vrf",
|
|
96
|
+
"vrf",
|
|
97
|
+
"role",
|
|
98
|
+
"last_seen",
|
|
99
|
+
"tag",
|
|
100
|
+
]
|
|
101
|
+
|
|
102
|
+
def search(self, queryset, name, value):
|
|
103
|
+
filters = (
|
|
104
|
+
Q(device__name=value)
|
|
105
|
+
| Q(raw_next_hop__icontains=value)
|
|
106
|
+
| Q(raw_bgp_prefix__icontains=value)
|
|
107
|
+
| Q(bgp_prefix__tenant__name__icontains=value)
|
|
108
|
+
| Q(raw_vrf__icontains=value)
|
|
109
|
+
| Q(vrf__name__icontains=value)
|
|
110
|
+
| Q(role__icontains=value)
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
return queryset.filter(filters)
|
|
114
|
+
|
|
115
|
+
def _vrf_none(self, queryset, name, value):
|
|
116
|
+
if value:
|
|
117
|
+
return queryset.filter(vrf=None)
|
|
118
|
+
else:
|
|
119
|
+
return queryset.filter(vrf__isnull=False)
|
|
120
|
+
|
|
121
|
+
# TODO: Filter `raw`` Address and Prefix with netaddr or treat it like a string?
|
|
122
|
+
"""
|
|
123
|
+
def filter_address(self, queryset, name, value):
|
|
124
|
+
# Let's first parse the addresses passed
|
|
125
|
+
# as argument. If they are all invalid,
|
|
126
|
+
# we return an empty queryset
|
|
127
|
+
# TODO: Use Netaddr or ipaddress module
|
|
128
|
+
value = self.parse_inet_addresses(value)
|
|
129
|
+
if len(value) == 0:
|
|
130
|
+
return queryset.none()
|
|
131
|
+
try:
|
|
132
|
+
return queryset.filter(address__net_in=value)
|
|
133
|
+
except ValidationError:
|
|
134
|
+
return queryset.none()
|
|
135
|
+
|
|
136
|
+
def filter_prefix(self, queryset, name, value):
|
|
137
|
+
query_values = []
|
|
138
|
+
for v in value:
|
|
139
|
+
try:
|
|
140
|
+
query_values.append(netaddr.IPNetwork(v))
|
|
141
|
+
except (AddrFormatError, ValueError):
|
|
142
|
+
pass
|
|
143
|
+
return queryset.filter(prefix__in=query_values)
|
|
144
|
+
"""
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import django_filters
|
|
2
|
+
from dcim.models import Device, Interface
|
|
3
|
+
from netbox.filtersets import NetBoxModelFilterSet
|
|
4
|
+
from tenancy.models import Tenant
|
|
5
|
+
|
|
6
|
+
from netbox_cesnet_services_plugin.models.bgpconnection import BGPConnection
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class BGPConnectionAggregationFilterSet(NetBoxModelFilterSet):
|
|
10
|
+
"""FilterSet for BGP Connection Aggregation view"""
|
|
11
|
+
|
|
12
|
+
device = django_filters.ModelMultipleChoiceFilter(
|
|
13
|
+
queryset=Device.objects.all(), field_name="device", label="Device"
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
device_id = django_filters.ModelMultipleChoiceFilter(
|
|
17
|
+
queryset=Device.objects.all(),
|
|
18
|
+
field_name="device__id",
|
|
19
|
+
to_field_name="id",
|
|
20
|
+
label="Device (ID)",
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
next_hop_interface = django_filters.ModelMultipleChoiceFilter(
|
|
24
|
+
queryset=Interface.objects.all(),
|
|
25
|
+
field_name="next_hop__interface",
|
|
26
|
+
label="Next Hop Interface",
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
next_hop_interface_id = django_filters.ModelMultipleChoiceFilter(
|
|
30
|
+
queryset=Interface.objects.all(),
|
|
31
|
+
field_name="next_hop__interface__id",
|
|
32
|
+
to_field_name="id",
|
|
33
|
+
label="Next Hop Interface (ID)",
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
bgp_prefix_tenant = django_filters.ModelMultipleChoiceFilter(
|
|
37
|
+
queryset=Tenant.objects.all(),
|
|
38
|
+
field_name="bgp_prefix__tenant",
|
|
39
|
+
label="BGP Prefix Tenant",
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
bgp_prefix_tenant_id = django_filters.ModelMultipleChoiceFilter(
|
|
43
|
+
queryset=Tenant.objects.all(),
|
|
44
|
+
field_name="bgp_prefix__tenant__id",
|
|
45
|
+
to_field_name="id",
|
|
46
|
+
label="BGP Prefix Tenant (ID)",
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
has_tenant = django_filters.BooleanFilter(method="_has_tenant", label="Has Tenant")
|
|
50
|
+
|
|
51
|
+
def _has_tenant(self, queryset, name, value):
|
|
52
|
+
"""Filter by whether the BGP connection has a tenant or not"""
|
|
53
|
+
if value:
|
|
54
|
+
return queryset.exclude(bgp_prefix__tenant__isnull=True)
|
|
55
|
+
else:
|
|
56
|
+
return queryset.filter(bgp_prefix__tenant__isnull=True)
|
|
57
|
+
|
|
58
|
+
class Meta:
|
|
59
|
+
model = BGPConnection
|
|
60
|
+
fields = (
|
|
61
|
+
"device",
|
|
62
|
+
"device_id",
|
|
63
|
+
"next_hop_interface",
|
|
64
|
+
"next_hop_interface_id",
|
|
65
|
+
"bgp_prefix_tenant",
|
|
66
|
+
"bgp_prefix_tenant_id",
|
|
67
|
+
"has_tenant",
|
|
68
|
+
)
|