|
3 | 3 | from django.shortcuts import render |
4 | 4 | from django.views.generic import View |
5 | 5 | from dcim.models import Cable, Device, Interface, DeviceRole |
| 6 | +from ipam.models import VLAN |
6 | 7 | from .models import SavedTopology |
7 | 8 | from . import forms, filters |
8 | 9 | from django.contrib.auth.mixins import PermissionRequiredMixin |
|
11 | 12 | import json |
12 | 13 | import re |
13 | 14 |
|
| 15 | + |
14 | 16 | NETBOX_CURRENT_VERSION = version.parse(settings.VERSION) |
15 | 17 |
|
16 | 18 | # Default NeXt UI icons |
@@ -227,6 +229,91 @@ def filter_tags(tags): |
227 | 229 | tags = filtered_tags |
228 | 230 | return tags |
229 | 231 |
|
| 232 | +def get_vlan_topology(nb_devices_qs, vlans): |
| 233 | + |
| 234 | + topology_dict = {'nodes': [], 'links': []} |
| 235 | + device_roles = set() |
| 236 | + all_device_tags = set() |
| 237 | + multi_cable_connections = [] |
| 238 | + vlan = VLAN.objects.get(id=vlans[0]) |
| 239 | + interfaces = vlan.get_interfaces() |
| 240 | + filtred_devices = [d.id for d in nb_devices_qs] |
| 241 | + filtred_interfaces = [] |
| 242 | + for interface in interfaces: |
| 243 | + if interface.is_connectable: |
| 244 | + direct_device_id = interface.device.id |
| 245 | + interface_trace = interface.trace() |
| 246 | + if len(interface_trace) != 0: |
| 247 | + termination_b_iface = interface_trace[-1][-1] |
| 248 | + connected_device_id = termination_b_iface.device.id |
| 249 | + if (direct_device_id in filtred_devices) or (direct_device_id in filtred_devices): |
| 250 | + filtred_interfaces.append(interface) |
| 251 | + |
| 252 | + |
| 253 | + |
| 254 | + devices = [] |
| 255 | + for interface in filtred_interfaces: |
| 256 | + if interface.is_connectable: |
| 257 | + if interface.device not in devices: |
| 258 | + devices.append(interface.device) |
| 259 | + interface_trace = interface.trace() |
| 260 | + if len(interface_trace) != 0: |
| 261 | + termination_b_iface = interface_trace[-1][-1] |
| 262 | + if termination_b_iface.device not in devices: |
| 263 | + devices.append(termination_b_iface.device) |
| 264 | + |
| 265 | + |
| 266 | + device_ids = [d.id for d in devices] |
| 267 | + for device in devices: |
| 268 | + device_is_passive = False |
| 269 | + device_url = device.get_absolute_url() |
| 270 | + primary_ip = '' |
| 271 | + if device.primary_ip: |
| 272 | + primary_ip = str(device.primary_ip.address) |
| 273 | + tags = [str(tag) for tag in device.tags.names()] |
| 274 | + for tag in tags: |
| 275 | + all_device_tags.add((tag, not tag_is_hidden(tag))) |
| 276 | + topology_dict['nodes'].append({ |
| 277 | + 'id': device.id, |
| 278 | + 'name': device.name, |
| 279 | + 'dcimDeviceLink': device_url, |
| 280 | + 'primaryIP': primary_ip, |
| 281 | + 'serial_number': device.serial, |
| 282 | + 'model': device.device_type.model, |
| 283 | + 'deviceRole': device.device_role.slug, |
| 284 | + 'layerSortPreference': get_node_layer_sort_preference( |
| 285 | + device.device_role.slug |
| 286 | + ), |
| 287 | + 'icon': get_icon_type( |
| 288 | + device.id |
| 289 | + ), |
| 290 | + 'isPassive': device_is_passive, |
| 291 | + 'tags': tags, |
| 292 | + }) |
| 293 | + is_visible = not (device.device_role.slug in UNDISPLAYED_DEVICE_ROLE_SLUGS) |
| 294 | + device_roles.add((device.device_role.slug, device.device_role.name, is_visible)) |
| 295 | + |
| 296 | + mapped_links = [] |
| 297 | + for interface in filtred_interfaces: |
| 298 | + if interface.is_connectable: |
| 299 | + interface_trace = interface.trace() |
| 300 | + if len(interface_trace) != 0: |
| 301 | + source_cable = interface_trace[0] |
| 302 | + dest_cable = interface_trace[-1] |
| 303 | + mapping_link = [source_cable[0].device.id,dest_cable[-1].device.id] |
| 304 | + if (mapping_link not in mapped_links) and (mapping_link.reverse() not in mapped_links): |
| 305 | + mapped_links.append(mapping_link) |
| 306 | + |
| 307 | + topology_dict['links'].append({ |
| 308 | + 'id': source_cable[1].id, |
| 309 | + 'source': source_cable[0].device.id, |
| 310 | + 'target': dest_cable[-1].device.id, |
| 311 | + "srcIfName": if_shortname(source_cable[0].name), |
| 312 | + "tgtIfName": if_shortname(dest_cable[-1].name), |
| 313 | + }) |
| 314 | + |
| 315 | + return topology_dict, device_roles, multi_cable_connections, list(all_device_tags) |
| 316 | + |
230 | 317 |
|
231 | 318 | def get_topology(nb_devices_qs): |
232 | 319 | topology_dict = {'nodes': [], 'links': []} |
@@ -398,8 +485,19 @@ def get(self, request): |
398 | 485 | if saved_topology_id is not None: |
399 | 486 | topology_dict, device_roles, device_tags, layout_context = get_saved_topology(saved_topology_id) |
400 | 487 | else: |
401 | | - self.queryset = self.filterset(request.GET, self.queryset).qs |
402 | | - topology_dict, device_roles, multi_cable_connections, device_tags = get_topology(self.queryset) |
| 488 | + vlans = [] |
| 489 | + if 'vlan_id' in request.GET: |
| 490 | + clean_request = request.GET.copy() |
| 491 | + clean_request.pop('vlan_id') |
| 492 | + vlans = request.GET.get('vlan_id') |
| 493 | + else: |
| 494 | + clean_request = request.GET.copy() |
| 495 | + |
| 496 | + self.queryset = self.filterset(clean_request, self.queryset).qs |
| 497 | + if len(vlans) == 0: |
| 498 | + topology_dict, device_roles, multi_cable_connections, device_tags = get_topology(self.queryset) |
| 499 | + else: |
| 500 | + topology_dict, device_roles, multi_cable_connections, device_tags = get_vlan_topology(self.queryset, vlans) |
403 | 501 |
|
404 | 502 | return render(request, self.template_name, { |
405 | 503 | 'source_data': json.dumps(topology_dict), |
|
0 commit comments