netbox-services 0.0.1__tar.gz
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_services-0.0.1/PKG-INFO +77 -0
- netbox_services-0.0.1/README.md +57 -0
- netbox_services-0.0.1/netbox_services/__init__.py +19 -0
- netbox_services-0.0.1/netbox_services/api/__init__.py +1 -0
- netbox_services-0.0.1/netbox_services/api/serializers.py +20 -0
- netbox_services-0.0.1/netbox_services/api/urls.py +7 -0
- netbox_services-0.0.1/netbox_services/api/views.py +8 -0
- netbox_services-0.0.1/netbox_services/filtersets.py +8 -0
- netbox_services-0.0.1/netbox_services/forms.py +148 -0
- netbox_services-0.0.1/netbox_services/migrations/0001_initial.py +43 -0
- netbox_services-0.0.1/netbox_services/migrations/0002_alter_service_asns_alter_service_cables_and_more.py +72 -0
- netbox_services-0.0.1/netbox_services/migrations/0003_alter_service_options_alter_service_asns_and_more.py +71 -0
- netbox_services-0.0.1/netbox_services/migrations/0004_rename_vrf_service_vrfs_alter_service_service_id.py +23 -0
- netbox_services-0.0.1/netbox_services/migrations/__init__.py +0 -0
- netbox_services-0.0.1/netbox_services/models.py +105 -0
- netbox_services-0.0.1/netbox_services/navigation.py +24 -0
- netbox_services-0.0.1/netbox_services/tables.py +46 -0
- netbox_services-0.0.1/netbox_services/urls.py +73 -0
- netbox_services-0.0.1/netbox_services/views.py +112 -0
- netbox_services-0.0.1/netbox_services.egg-info/PKG-INFO +77 -0
- netbox_services-0.0.1/netbox_services.egg-info/SOURCES.txt +23 -0
- netbox_services-0.0.1/netbox_services.egg-info/dependency_links.txt +1 -0
- netbox_services-0.0.1/netbox_services.egg-info/top_level.txt +2 -0
- netbox_services-0.0.1/pyproject.toml +41 -0
- netbox_services-0.0.1/setup.cfg +4 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: netbox-services
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: A NetBox services Plugin for Service Providers
|
|
5
|
+
Author-email: Arturo Baldo <baldoarturo@gmail.com>
|
|
6
|
+
Maintainer-email: Arturo Baldo <baldoarturo@gmail.com>
|
|
7
|
+
Project-URL: Documentation, https://github.com/baldoarturo/netbox-services/blob/main/README.md
|
|
8
|
+
Project-URL: Source, https://github.com/baldoarturo/netbox-services
|
|
9
|
+
Project-URL: Tracker, https://github.com/baldoarturo/netbox-services/issues
|
|
10
|
+
Keywords: netbox-plugin
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Natural Language :: English
|
|
14
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Requires-Python: >=3.10
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
|
|
21
|
+
# NetBox Services Plugin
|
|
22
|
+
|
|
23
|
+
This plugin extends NetBox to manage and relate business services to network resources. It introduces a `Service` model that allows you to track various service types (such as L2VPN, L3VPN, DIA, Transit, CDN, Voice) and associate them with devices, interfaces, cables, VLANs, prefixes, VRFs, ASNs, route targets, L2VPNs, tunnels, and virtual machines.
|
|
24
|
+
|
|
25
|
+
## Features
|
|
26
|
+
- Add, edit, and delete business services.
|
|
27
|
+
- Relate services to network objects (devices, interfaces, cables, VLANs, prefixes, VRFs, ASNs, route targets, L2VPNs, tunnels, virtual machines).
|
|
28
|
+
- Filter and view services in a table with all relevant fields.
|
|
29
|
+
- Custom forms and views for relating specific network objects to a service.
|
|
30
|
+
- Integrated navigation and changelog support.
|
|
31
|
+
|
|
32
|
+
## Usage
|
|
33
|
+
- Access the plugin from the NetBox navigation menu under "Business Services".
|
|
34
|
+
- Create new services and relate them to network resources.
|
|
35
|
+
- Use the detail view to see all associations for a service.
|
|
36
|
+
|
|
37
|
+

|
|
38
|
+
|
|
39
|
+
## Why
|
|
40
|
+
Because you might be looking for such a thing.
|
|
41
|
+
|
|
42
|
+
Tagging is great for simple categorization, but the NetBox Services plugin goes far beyond that by letting you model real business services and their relationships to network resources.
|
|
43
|
+
|
|
44
|
+
Instead of just tagging a device or prefix as "DIA," you can create a full DIA service—like "NW-123456" from Cogent—and link it to all relevant devices, interfaces, prefixes, VRFs, ASNs, and more.
|
|
45
|
+
|
|
46
|
+
For example, with a DIA service from Cogent (Service ID: NW-123456), you can:
|
|
47
|
+
|
|
48
|
+
- See all devices and interfaces delivering that service.
|
|
49
|
+
- Track the exact IP prefixes, VRFs, and ASNs involved.
|
|
50
|
+
- Relate cables, tunnels, and even virtual machines to the service.
|
|
51
|
+
- View and manage all these relationships in one place, with history and forms tailored to each resource.
|
|
52
|
+
|
|
53
|
+
This gives you a true service-centric view of your network, making troubleshooting, reporting, and change management much more powerful and organized than simple tagging ever could.
|
|
54
|
+
|
|
55
|
+
## Requirements
|
|
56
|
+
- NetBox 4.x or later
|
|
57
|
+
- Django 4.x or later
|
|
58
|
+
|
|
59
|
+
## Installation
|
|
60
|
+
1. Clone this repository into your NetBox `plugins` directory. You can also install it on your system / venv / coffee maker with
|
|
61
|
+
```bash
|
|
62
|
+
pip install netbox_services
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
2. Add `'netbox_services'` to the `PLUGINS` list in your NetBox configuration.
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
PLUGINS = [
|
|
69
|
+
'netbox_services'
|
|
70
|
+
],
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
3. Run migrations: `python manage.py migrate netbox_services`
|
|
74
|
+
4. Restart NetBox.
|
|
75
|
+
|
|
76
|
+
## License
|
|
77
|
+
MIT
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# NetBox Services Plugin
|
|
2
|
+
|
|
3
|
+
This plugin extends NetBox to manage and relate business services to network resources. It introduces a `Service` model that allows you to track various service types (such as L2VPN, L3VPN, DIA, Transit, CDN, Voice) and associate them with devices, interfaces, cables, VLANs, prefixes, VRFs, ASNs, route targets, L2VPNs, tunnels, and virtual machines.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
- Add, edit, and delete business services.
|
|
7
|
+
- Relate services to network objects (devices, interfaces, cables, VLANs, prefixes, VRFs, ASNs, route targets, L2VPNs, tunnels, virtual machines).
|
|
8
|
+
- Filter and view services in a table with all relevant fields.
|
|
9
|
+
- Custom forms and views for relating specific network objects to a service.
|
|
10
|
+
- Integrated navigation and changelog support.
|
|
11
|
+
|
|
12
|
+
## Usage
|
|
13
|
+
- Access the plugin from the NetBox navigation menu under "Business Services".
|
|
14
|
+
- Create new services and relate them to network resources.
|
|
15
|
+
- Use the detail view to see all associations for a service.
|
|
16
|
+
|
|
17
|
+

|
|
18
|
+
|
|
19
|
+
## Why
|
|
20
|
+
Because you might be looking for such a thing.
|
|
21
|
+
|
|
22
|
+
Tagging is great for simple categorization, but the NetBox Services plugin goes far beyond that by letting you model real business services and their relationships to network resources.
|
|
23
|
+
|
|
24
|
+
Instead of just tagging a device or prefix as "DIA," you can create a full DIA service—like "NW-123456" from Cogent—and link it to all relevant devices, interfaces, prefixes, VRFs, ASNs, and more.
|
|
25
|
+
|
|
26
|
+
For example, with a DIA service from Cogent (Service ID: NW-123456), you can:
|
|
27
|
+
|
|
28
|
+
- See all devices and interfaces delivering that service.
|
|
29
|
+
- Track the exact IP prefixes, VRFs, and ASNs involved.
|
|
30
|
+
- Relate cables, tunnels, and even virtual machines to the service.
|
|
31
|
+
- View and manage all these relationships in one place, with history and forms tailored to each resource.
|
|
32
|
+
|
|
33
|
+
This gives you a true service-centric view of your network, making troubleshooting, reporting, and change management much more powerful and organized than simple tagging ever could.
|
|
34
|
+
|
|
35
|
+
## Requirements
|
|
36
|
+
- NetBox 4.x or later
|
|
37
|
+
- Django 4.x or later
|
|
38
|
+
|
|
39
|
+
## Installation
|
|
40
|
+
1. Clone this repository into your NetBox `plugins` directory. You can also install it on your system / venv / coffee maker with
|
|
41
|
+
```bash
|
|
42
|
+
pip install netbox_services
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
2. Add `'netbox_services'` to the `PLUGINS` list in your NetBox configuration.
|
|
46
|
+
|
|
47
|
+
```python
|
|
48
|
+
PLUGINS = [
|
|
49
|
+
'netbox_services'
|
|
50
|
+
],
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
3. Run migrations: `python manage.py migrate netbox_services`
|
|
54
|
+
4. Restart NetBox.
|
|
55
|
+
|
|
56
|
+
## License
|
|
57
|
+
MIT
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from importlib.metadata import metadata
|
|
2
|
+
|
|
3
|
+
from netbox.plugins import PluginConfig
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
plugin = metadata('netbox_services')
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Services(PluginConfig):
|
|
10
|
+
name = plugin.get('Name').replace('-', '_')
|
|
11
|
+
verbose_name = plugin.get('Name').replace('-', ' ').title()
|
|
12
|
+
description = plugin.get('Summary')
|
|
13
|
+
version = plugin.get('Version')
|
|
14
|
+
author = 'Arturo Baldo'
|
|
15
|
+
author_email = 'baldoarturo@gmail.com'
|
|
16
|
+
base_url = 'services'
|
|
17
|
+
min_version = '4.4.0'
|
|
18
|
+
|
|
19
|
+
config = Services
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .serializers import *
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from rest_framework import serializers
|
|
2
|
+
|
|
3
|
+
from netbox.api.serializers import NetBoxModelSerializer
|
|
4
|
+
from netbox_services.models import Service
|
|
5
|
+
|
|
6
|
+
class ServiceSerializer(NetBoxModelSerializer):
|
|
7
|
+
|
|
8
|
+
url = serializers.HyperlinkedIdentityField(
|
|
9
|
+
view_name='plugins-api:netbox_services-api:service-detail'
|
|
10
|
+
)
|
|
11
|
+
class Meta:
|
|
12
|
+
model = Service
|
|
13
|
+
fields = ('type',
|
|
14
|
+
'service_id',
|
|
15
|
+
'tenant',
|
|
16
|
+
'tags',
|
|
17
|
+
'custom_fields',
|
|
18
|
+
'created',
|
|
19
|
+
'last_updated',
|
|
20
|
+
)
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
from netbox.api.viewsets import NetBoxModelViewSet
|
|
2
|
+
|
|
3
|
+
from .. import models
|
|
4
|
+
from .serializers import ServiceSerializer
|
|
5
|
+
|
|
6
|
+
class ServiceViewSet(NetBoxModelViewSet):
|
|
7
|
+
queryset = models.Service.objects.prefetch_related('tags')
|
|
8
|
+
serializer_class = ServiceSerializer
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
from django import forms
|
|
2
|
+
from utilities.forms.fields import CommentField
|
|
3
|
+
|
|
4
|
+
from netbox.forms import NetBoxModelForm, NetBoxModelFilterSetForm
|
|
5
|
+
from .models import Service, ServiceTypeChoices
|
|
6
|
+
|
|
7
|
+
from tenancy.models import Tenant
|
|
8
|
+
from dcim.models import Device, Interface, Cable
|
|
9
|
+
from ipam.models import VRF, Prefix, VLAN, ASN, RouteTarget
|
|
10
|
+
from vpn.models import L2VPN, Tunnel
|
|
11
|
+
from virtualization.models import VirtualMachine
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class NewServiceForm(NetBoxModelForm):
|
|
15
|
+
comments = CommentField()
|
|
16
|
+
|
|
17
|
+
class Meta:
|
|
18
|
+
model = Service
|
|
19
|
+
fields = ('type', 'service_id', 'tenant')
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class ServiceRelatedDevicesForm(forms.ModelForm):
|
|
23
|
+
|
|
24
|
+
class Meta:
|
|
25
|
+
model = Service
|
|
26
|
+
fields = ('devices',)
|
|
27
|
+
|
|
28
|
+
class ServiceRelatedInterfacesForm(forms.ModelForm):
|
|
29
|
+
|
|
30
|
+
class Meta:
|
|
31
|
+
model = Service
|
|
32
|
+
fields = ('interfaces',)
|
|
33
|
+
|
|
34
|
+
class ServiceRelatedCablesForm(forms.ModelForm):
|
|
35
|
+
|
|
36
|
+
class Meta:
|
|
37
|
+
model = Service
|
|
38
|
+
fields = ('cables',)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class ServiceRelatedVLANsForm(forms.ModelForm):
|
|
42
|
+
|
|
43
|
+
class Meta:
|
|
44
|
+
model = Service
|
|
45
|
+
fields = ('vlans',)
|
|
46
|
+
|
|
47
|
+
class ServiceRelatedPrefixesForm(forms.ModelForm):
|
|
48
|
+
|
|
49
|
+
class Meta:
|
|
50
|
+
model = Service
|
|
51
|
+
fields = ('prefixes',)
|
|
52
|
+
|
|
53
|
+
class ServiceRelatedVRFsForm(forms.ModelForm):
|
|
54
|
+
|
|
55
|
+
class Meta:
|
|
56
|
+
model = Service
|
|
57
|
+
fields = ('vrfs',)
|
|
58
|
+
|
|
59
|
+
class ServiceRelatedASNsForm(forms.ModelForm):
|
|
60
|
+
|
|
61
|
+
class Meta:
|
|
62
|
+
model = Service
|
|
63
|
+
fields = ('asns',)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class ServiceRelatedRouteTargetsForm(forms.ModelForm):
|
|
67
|
+
|
|
68
|
+
class Meta:
|
|
69
|
+
model = Service
|
|
70
|
+
fields = ('route_targets',)
|
|
71
|
+
|
|
72
|
+
class ServiceRelatedL2VPNsForm(forms.ModelForm):
|
|
73
|
+
|
|
74
|
+
class Meta:
|
|
75
|
+
model = Service
|
|
76
|
+
fields = ('l2vpns',)
|
|
77
|
+
|
|
78
|
+
class ServiceRelatedTunnelsForm(forms.ModelForm):
|
|
79
|
+
|
|
80
|
+
class Meta:
|
|
81
|
+
model = Service
|
|
82
|
+
fields = ('tunnels',)
|
|
83
|
+
|
|
84
|
+
class ServiceRelatedVirtualMachinesForm(forms.ModelForm):
|
|
85
|
+
|
|
86
|
+
class Meta:
|
|
87
|
+
model = Service
|
|
88
|
+
fields = ('virtual_machines',)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
class ServiceFilterForm(NetBoxModelFilterSetForm):
|
|
92
|
+
comments = CommentField()
|
|
93
|
+
model = Service
|
|
94
|
+
type = forms.MultipleChoiceField(
|
|
95
|
+
choices=ServiceTypeChoices,
|
|
96
|
+
required=False
|
|
97
|
+
)
|
|
98
|
+
service_id = forms.CharField(
|
|
99
|
+
required=False
|
|
100
|
+
)
|
|
101
|
+
tenant = forms.ModelMultipleChoiceField(
|
|
102
|
+
queryset=Tenant.objects.all(),
|
|
103
|
+
required=False
|
|
104
|
+
)
|
|
105
|
+
devices = forms.ModelMultipleChoiceField(
|
|
106
|
+
queryset=Device.objects.all(),
|
|
107
|
+
required=False
|
|
108
|
+
)
|
|
109
|
+
interfaces = forms.ModelMultipleChoiceField(
|
|
110
|
+
queryset=Interface.objects.all(),
|
|
111
|
+
required=False
|
|
112
|
+
)
|
|
113
|
+
cables = forms.ModelMultipleChoiceField(
|
|
114
|
+
queryset=Cable.objects.all(),
|
|
115
|
+
required=False
|
|
116
|
+
)
|
|
117
|
+
vlans = forms.ModelMultipleChoiceField(
|
|
118
|
+
queryset=VLAN.objects.all(),
|
|
119
|
+
required=False
|
|
120
|
+
)
|
|
121
|
+
prefixes = forms.ModelMultipleChoiceField(
|
|
122
|
+
queryset=Prefix.objects.all(),
|
|
123
|
+
required=False
|
|
124
|
+
)
|
|
125
|
+
vrf = forms.ModelMultipleChoiceField(
|
|
126
|
+
queryset=VRF.objects.all(),
|
|
127
|
+
required=False
|
|
128
|
+
)
|
|
129
|
+
asns = forms.ModelMultipleChoiceField(
|
|
130
|
+
queryset=ASN.objects.all(),
|
|
131
|
+
required=False
|
|
132
|
+
)
|
|
133
|
+
route_targets = forms.ModelMultipleChoiceField(
|
|
134
|
+
queryset=RouteTarget.objects.all(),
|
|
135
|
+
required=False
|
|
136
|
+
)
|
|
137
|
+
l2vpns = forms.ModelMultipleChoiceField(
|
|
138
|
+
queryset=L2VPN.objects.all(),
|
|
139
|
+
required=False
|
|
140
|
+
)
|
|
141
|
+
tunnels = forms.ModelMultipleChoiceField(
|
|
142
|
+
queryset=Tenant.objects.all(),
|
|
143
|
+
required=False
|
|
144
|
+
)
|
|
145
|
+
virtual_machines = forms.ModelMultipleChoiceField(
|
|
146
|
+
queryset=VirtualMachine.objects.all(),
|
|
147
|
+
required=False
|
|
148
|
+
)
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Generated by Django 5.2.6 on 2025-09-27 20:31
|
|
2
|
+
|
|
3
|
+
import django.db.models.deletion
|
|
4
|
+
import netbox.models.deletion
|
|
5
|
+
import taggit.managers
|
|
6
|
+
import utilities.json
|
|
7
|
+
from django.db import migrations, models
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Migration(migrations.Migration):
|
|
11
|
+
|
|
12
|
+
initial = True
|
|
13
|
+
|
|
14
|
+
operations = [
|
|
15
|
+
migrations.CreateModel(
|
|
16
|
+
name='Service',
|
|
17
|
+
fields=[
|
|
18
|
+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)),
|
|
19
|
+
('created', models.DateTimeField(auto_now_add=True, null=True)),
|
|
20
|
+
('last_updated', models.DateTimeField(auto_now=True, null=True)),
|
|
21
|
+
('custom_field_data', models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder)),
|
|
22
|
+
('type', models.CharField()),
|
|
23
|
+
('service_id', models.CharField()),
|
|
24
|
+
('asns', models.ManyToManyField(to='ipam.asn')),
|
|
25
|
+
('cables', models.ManyToManyField(to='dcim.cable')),
|
|
26
|
+
('devices', models.ManyToManyField(to='dcim.device')),
|
|
27
|
+
('interfaces', models.ManyToManyField(to='dcim.interface')),
|
|
28
|
+
('l2vpns', models.ManyToManyField(to='vpn.l2vpn')),
|
|
29
|
+
('prefixes', models.ManyToManyField(to='ipam.prefix')),
|
|
30
|
+
('route_targets', models.ManyToManyField(to='ipam.routetarget')),
|
|
31
|
+
('tags', taggit.managers.TaggableManager(through='taggit.TaggedItem', to='taggit.Tag')),
|
|
32
|
+
('tenant', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='tenancy.tenant')),
|
|
33
|
+
('tunnels', models.ManyToManyField(to='vpn.tunnel')),
|
|
34
|
+
('virtual_machines', models.ManyToManyField(to='virtualization.virtualmachine')),
|
|
35
|
+
('vlans', models.ManyToManyField(to='ipam.vlan')),
|
|
36
|
+
('vrf', models.ManyToManyField(to='ipam.vrf')),
|
|
37
|
+
],
|
|
38
|
+
options={
|
|
39
|
+
'abstract': False,
|
|
40
|
+
},
|
|
41
|
+
bases=(netbox.models.deletion.DeleteMixin, models.Model),
|
|
42
|
+
),
|
|
43
|
+
]
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Generated by Django 5.2.6 on 2025-09-27 20:54
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Migration(migrations.Migration):
|
|
7
|
+
|
|
8
|
+
dependencies = [
|
|
9
|
+
('dcim', '0215_rackreservation_status'),
|
|
10
|
+
('ipam', '0082_add_prefix_network_containment_indexes'),
|
|
11
|
+
('netbox_services', '0001_initial'),
|
|
12
|
+
('virtualization', '0048_populate_mac_addresses'),
|
|
13
|
+
('vpn', '0009_remove_redundant_indexes'),
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
operations = [
|
|
17
|
+
migrations.AlterField(
|
|
18
|
+
model_name='service',
|
|
19
|
+
name='asns',
|
|
20
|
+
field=models.ManyToManyField(blank=True, null=True, to='ipam.asn'),
|
|
21
|
+
),
|
|
22
|
+
migrations.AlterField(
|
|
23
|
+
model_name='service',
|
|
24
|
+
name='cables',
|
|
25
|
+
field=models.ManyToManyField(blank=True, to='dcim.cable'),
|
|
26
|
+
),
|
|
27
|
+
migrations.AlterField(
|
|
28
|
+
model_name='service',
|
|
29
|
+
name='devices',
|
|
30
|
+
field=models.ManyToManyField(blank=True, null=True, to='dcim.device'),
|
|
31
|
+
),
|
|
32
|
+
migrations.AlterField(
|
|
33
|
+
model_name='service',
|
|
34
|
+
name='interfaces',
|
|
35
|
+
field=models.ManyToManyField(blank=True, null=True, to='dcim.interface'),
|
|
36
|
+
),
|
|
37
|
+
migrations.AlterField(
|
|
38
|
+
model_name='service',
|
|
39
|
+
name='l2vpns',
|
|
40
|
+
field=models.ManyToManyField(blank=True, null=True, to='vpn.l2vpn'),
|
|
41
|
+
),
|
|
42
|
+
migrations.AlterField(
|
|
43
|
+
model_name='service',
|
|
44
|
+
name='prefixes',
|
|
45
|
+
field=models.ManyToManyField(blank=True, null=True, to='ipam.prefix'),
|
|
46
|
+
),
|
|
47
|
+
migrations.AlterField(
|
|
48
|
+
model_name='service',
|
|
49
|
+
name='route_targets',
|
|
50
|
+
field=models.ManyToManyField(blank=True, null=True, to='ipam.routetarget'),
|
|
51
|
+
),
|
|
52
|
+
migrations.AlterField(
|
|
53
|
+
model_name='service',
|
|
54
|
+
name='tunnels',
|
|
55
|
+
field=models.ManyToManyField(blank=True, null=True, to='vpn.tunnel'),
|
|
56
|
+
),
|
|
57
|
+
migrations.AlterField(
|
|
58
|
+
model_name='service',
|
|
59
|
+
name='virtual_machines',
|
|
60
|
+
field=models.ManyToManyField(blank=True, null=True, to='virtualization.virtualmachine'),
|
|
61
|
+
),
|
|
62
|
+
migrations.AlterField(
|
|
63
|
+
model_name='service',
|
|
64
|
+
name='vlans',
|
|
65
|
+
field=models.ManyToManyField(blank=True, null=True, to='ipam.vlan'),
|
|
66
|
+
),
|
|
67
|
+
migrations.AlterField(
|
|
68
|
+
model_name='service',
|
|
69
|
+
name='vrf',
|
|
70
|
+
field=models.ManyToManyField(blank=True, to='ipam.vrf'),
|
|
71
|
+
),
|
|
72
|
+
]
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Generated by Django 5.2.6 on 2025-10-01 19:09
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Migration(migrations.Migration):
|
|
7
|
+
|
|
8
|
+
dependencies = [
|
|
9
|
+
('dcim', '0215_rackreservation_status'),
|
|
10
|
+
('ipam', '0082_add_prefix_network_containment_indexes'),
|
|
11
|
+
('netbox_services', '0002_alter_service_asns_alter_service_cables_and_more'),
|
|
12
|
+
('virtualization', '0048_populate_mac_addresses'),
|
|
13
|
+
('vpn', '0009_remove_redundant_indexes'),
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
operations = [
|
|
17
|
+
migrations.AlterModelOptions(
|
|
18
|
+
name='service',
|
|
19
|
+
options={'ordering': ['service_id']},
|
|
20
|
+
),
|
|
21
|
+
migrations.AlterField(
|
|
22
|
+
model_name='service',
|
|
23
|
+
name='asns',
|
|
24
|
+
field=models.ManyToManyField(to='ipam.asn'),
|
|
25
|
+
),
|
|
26
|
+
migrations.AlterField(
|
|
27
|
+
model_name='service',
|
|
28
|
+
name='cables',
|
|
29
|
+
field=models.ManyToManyField(to='dcim.cable'),
|
|
30
|
+
),
|
|
31
|
+
migrations.AlterField(
|
|
32
|
+
model_name='service',
|
|
33
|
+
name='devices',
|
|
34
|
+
field=models.ManyToManyField(to='dcim.device'),
|
|
35
|
+
),
|
|
36
|
+
migrations.AlterField(
|
|
37
|
+
model_name='service',
|
|
38
|
+
name='interfaces',
|
|
39
|
+
field=models.ManyToManyField(to='dcim.interface'),
|
|
40
|
+
),
|
|
41
|
+
migrations.AlterField(
|
|
42
|
+
model_name='service',
|
|
43
|
+
name='l2vpns',
|
|
44
|
+
field=models.ManyToManyField(to='vpn.l2vpn'),
|
|
45
|
+
),
|
|
46
|
+
migrations.AlterField(
|
|
47
|
+
model_name='service',
|
|
48
|
+
name='prefixes',
|
|
49
|
+
field=models.ManyToManyField(to='ipam.prefix'),
|
|
50
|
+
),
|
|
51
|
+
migrations.AlterField(
|
|
52
|
+
model_name='service',
|
|
53
|
+
name='route_targets',
|
|
54
|
+
field=models.ManyToManyField(to='ipam.routetarget'),
|
|
55
|
+
),
|
|
56
|
+
migrations.AlterField(
|
|
57
|
+
model_name='service',
|
|
58
|
+
name='tunnels',
|
|
59
|
+
field=models.ManyToManyField(to='vpn.tunnel'),
|
|
60
|
+
),
|
|
61
|
+
migrations.AlterField(
|
|
62
|
+
model_name='service',
|
|
63
|
+
name='virtual_machines',
|
|
64
|
+
field=models.ManyToManyField(to='virtualization.virtualmachine'),
|
|
65
|
+
),
|
|
66
|
+
migrations.AlterField(
|
|
67
|
+
model_name='service',
|
|
68
|
+
name='vlans',
|
|
69
|
+
field=models.ManyToManyField(to='ipam.vlan'),
|
|
70
|
+
),
|
|
71
|
+
]
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Generated by Django 5.2.6 on 2025-10-02 19:48
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Migration(migrations.Migration):
|
|
7
|
+
|
|
8
|
+
dependencies = [
|
|
9
|
+
('netbox_services', '0003_alter_service_options_alter_service_asns_and_more'),
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
operations = [
|
|
13
|
+
migrations.RenameField(
|
|
14
|
+
model_name='service',
|
|
15
|
+
old_name='vrf',
|
|
16
|
+
new_name='vrfs',
|
|
17
|
+
),
|
|
18
|
+
migrations.AlterField(
|
|
19
|
+
model_name='service',
|
|
20
|
+
name='service_id',
|
|
21
|
+
field=models.CharField(unique=True),
|
|
22
|
+
),
|
|
23
|
+
]
|
|
File without changes
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
from django.db import models
|
|
2
|
+
from django.urls import reverse
|
|
3
|
+
|
|
4
|
+
from netbox.models import NetBoxModel
|
|
5
|
+
|
|
6
|
+
from tenancy.models import Tenant
|
|
7
|
+
from dcim.models import Device, Interface, Cable
|
|
8
|
+
from ipam.models import VRF, Prefix, VLAN, ASN, RouteTarget
|
|
9
|
+
from vpn.models import L2VPN, Tunnel
|
|
10
|
+
from virtualization.models import VirtualMachine
|
|
11
|
+
|
|
12
|
+
from utilities.choices import ChoiceSet
|
|
13
|
+
from taggit.managers import TaggableManager
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class ServiceTypeChoices(ChoiceSet):
|
|
17
|
+
CHOICES = [
|
|
18
|
+
('l2vpn', 'L2VPN'),
|
|
19
|
+
('l3vpn', 'L3VPN'),
|
|
20
|
+
('dia', 'DIA'),
|
|
21
|
+
('transit', 'IP Transit'),
|
|
22
|
+
('cdn', 'CDN'),
|
|
23
|
+
('voice', 'Voice')
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class Service(NetBoxModel):
|
|
28
|
+
type = models.CharField(
|
|
29
|
+
choices=ServiceTypeChoices,
|
|
30
|
+
verbose_name='Service Type',
|
|
31
|
+
null=False,
|
|
32
|
+
blank=False
|
|
33
|
+
)
|
|
34
|
+
service_id = models.CharField(
|
|
35
|
+
verbose_name='Service ID',
|
|
36
|
+
unique=True,
|
|
37
|
+
null=False,
|
|
38
|
+
blank=False
|
|
39
|
+
)
|
|
40
|
+
tenant = models.ForeignKey(
|
|
41
|
+
Tenant,
|
|
42
|
+
on_delete=models.PROTECT,
|
|
43
|
+
verbose_name='Service Tenant',
|
|
44
|
+
null=True,
|
|
45
|
+
blank=True
|
|
46
|
+
)
|
|
47
|
+
devices = models.ManyToManyField(
|
|
48
|
+
Device,
|
|
49
|
+
verbose_name='Related Devices',
|
|
50
|
+
)
|
|
51
|
+
interfaces = models.ManyToManyField(
|
|
52
|
+
Interface,
|
|
53
|
+
verbose_name='Related interfaces',
|
|
54
|
+
)
|
|
55
|
+
cables = models.ManyToManyField(
|
|
56
|
+
Cable,
|
|
57
|
+
verbose_name='Related Cables/XConnects',
|
|
58
|
+
)
|
|
59
|
+
vlans = models.ManyToManyField(
|
|
60
|
+
VLAN,
|
|
61
|
+
verbose_name='Related VLANs',
|
|
62
|
+
)
|
|
63
|
+
prefixes = models.ManyToManyField(
|
|
64
|
+
Prefix,
|
|
65
|
+
verbose_name='Related IP Prefixes',
|
|
66
|
+
)
|
|
67
|
+
vrfs = models.ManyToManyField(
|
|
68
|
+
VRF,
|
|
69
|
+
verbose_name='Related VRF',
|
|
70
|
+
blank=True
|
|
71
|
+
)
|
|
72
|
+
asns = models.ManyToManyField(
|
|
73
|
+
ASN,
|
|
74
|
+
verbose_name='Related Autonomous Systems',
|
|
75
|
+
)
|
|
76
|
+
route_targets = models.ManyToManyField(
|
|
77
|
+
RouteTarget,
|
|
78
|
+
verbose_name='Related Route Targets',
|
|
79
|
+
)
|
|
80
|
+
l2vpns = models.ManyToManyField(
|
|
81
|
+
L2VPN,
|
|
82
|
+
verbose_name='Related Route Targets',
|
|
83
|
+
)
|
|
84
|
+
tunnels = models.ManyToManyField(
|
|
85
|
+
Tunnel,
|
|
86
|
+
verbose_name='Related Tunnels',
|
|
87
|
+
)
|
|
88
|
+
virtual_machines = models.ManyToManyField(
|
|
89
|
+
VirtualMachine,
|
|
90
|
+
verbose_name='Related Virtual Machines',
|
|
91
|
+
)
|
|
92
|
+
tags = TaggableManager(
|
|
93
|
+
related_name='netbox_services_service_set',
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
class Meta:
|
|
97
|
+
verbose_name = 'Service'
|
|
98
|
+
verbose_name_plural = 'Services'
|
|
99
|
+
ordering = ['service_id']
|
|
100
|
+
|
|
101
|
+
def __str__(self):
|
|
102
|
+
return f"{self.service_id}"
|
|
103
|
+
|
|
104
|
+
def get_absolute_url(self):
|
|
105
|
+
return f"/plugins/services/{self.pk}/"
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from netbox.plugins import PluginMenu
|
|
2
|
+
from netbox.plugins import PluginMenuItem, PluginMenuButton
|
|
3
|
+
|
|
4
|
+
services = PluginMenuItem(
|
|
5
|
+
auth_required=True,
|
|
6
|
+
link='plugins:netbox_services:service_list',
|
|
7
|
+
link_text='Business Services',
|
|
8
|
+
buttons=(
|
|
9
|
+
PluginMenuButton(
|
|
10
|
+
link='plugins:netbox_services:service_add',
|
|
11
|
+
title='Add',
|
|
12
|
+
icon_class='mdi mdi-plus',
|
|
13
|
+
),
|
|
14
|
+
)
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
menu = PluginMenu(
|
|
19
|
+
label='Business Services',
|
|
20
|
+
groups=(
|
|
21
|
+
('Services', (services,)),
|
|
22
|
+
),
|
|
23
|
+
icon_class='mdi mdi-receipt-text-arrow-right'
|
|
24
|
+
)
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import django_tables2 as tables
|
|
2
|
+
|
|
3
|
+
from netbox.tables import NetBoxTable
|
|
4
|
+
|
|
5
|
+
from .models import Service
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class ServiceListTable(NetBoxTable):
|
|
9
|
+
service_id = tables.Column(
|
|
10
|
+
linkify=True,
|
|
11
|
+
verbose_name='Service ID',
|
|
12
|
+
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
class Meta(NetBoxTable.Meta):
|
|
16
|
+
model = Service
|
|
17
|
+
fields = ('pk', 'service_id', 'type', 'tenant')
|
|
18
|
+
default_columns = ('pk', 'service_id', 'type', 'tenant')
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class ServiceTable(NetBoxTable):
|
|
22
|
+
service_id = tables.Column(
|
|
23
|
+
linkify=True,
|
|
24
|
+
verbose_name='Service ID',
|
|
25
|
+
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
class Meta(NetBoxTable.Meta):
|
|
29
|
+
model = Service
|
|
30
|
+
fields = (
|
|
31
|
+
'type',
|
|
32
|
+
'service_id',
|
|
33
|
+
'tenant',
|
|
34
|
+
'devices',
|
|
35
|
+
'interfaces',
|
|
36
|
+
'cables',
|
|
37
|
+
'vlans',
|
|
38
|
+
'prefixes',
|
|
39
|
+
'vrf',
|
|
40
|
+
'asns',
|
|
41
|
+
'route_targets',
|
|
42
|
+
'l2vpns',
|
|
43
|
+
'tunnels',
|
|
44
|
+
'virtual_machines',
|
|
45
|
+
)
|
|
46
|
+
default_columns = ('pk', 'service_id', 'type', 'tenant')
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
from django.urls import path, include
|
|
2
|
+
from utilities.urls import get_model_urls
|
|
3
|
+
from .views import (
|
|
4
|
+
ServiceView,
|
|
5
|
+
ServiceListView,
|
|
6
|
+
ServiceAddView,
|
|
7
|
+
ServiceEditView,
|
|
8
|
+
ServiceDeleteView,
|
|
9
|
+
ServiceRelatedDevicesView,
|
|
10
|
+
ServiceRelatedInterfacesView,
|
|
11
|
+
ServiceRelatedCablesView,
|
|
12
|
+
ServiceRelatedVLANsView,
|
|
13
|
+
ServiceRelatedPrefixesView,
|
|
14
|
+
ServiceRelatedVRFsView,
|
|
15
|
+
ServiceRelatedASNsView,
|
|
16
|
+
ServiceRelatedRouteTargetsView,
|
|
17
|
+
ServiceRelatedL2VPNsView,
|
|
18
|
+
ServiceRelatedTunnelsView,
|
|
19
|
+
ServiceRelatedVirtualMachinesView,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
urlpatterns = [
|
|
23
|
+
path('',
|
|
24
|
+
include(get_model_urls('netbox_services', 'service', detail=False))
|
|
25
|
+
),
|
|
26
|
+
path('<int:pk>/',
|
|
27
|
+
include(get_model_urls('netbox_services', 'service', detail=True))
|
|
28
|
+
),
|
|
29
|
+
path('<int:pk>/relate/devices/',
|
|
30
|
+
ServiceRelatedDevicesView.as_view(),
|
|
31
|
+
name='relate_devices',
|
|
32
|
+
),
|
|
33
|
+
path('<int:pk>/relate/interfaces/',
|
|
34
|
+
ServiceRelatedInterfacesView.as_view(),
|
|
35
|
+
name='relate_interfaces',
|
|
36
|
+
),
|
|
37
|
+
path('<int:pk>/relate/cables/',
|
|
38
|
+
ServiceRelatedCablesView.as_view(),
|
|
39
|
+
name='relate_cables',
|
|
40
|
+
),
|
|
41
|
+
path('<int:pk>/relate/vlans/',
|
|
42
|
+
ServiceRelatedVLANsView.as_view(),
|
|
43
|
+
name='relate_vlans',
|
|
44
|
+
),
|
|
45
|
+
path('<int:pk>/relate/prefixes/',
|
|
46
|
+
ServiceRelatedPrefixesView.as_view(),
|
|
47
|
+
name='relate_prefixes',
|
|
48
|
+
),
|
|
49
|
+
path('<int:pk>/relate/vrfs/',
|
|
50
|
+
ServiceRelatedVRFsView.as_view(),
|
|
51
|
+
name='relate_vrfs',
|
|
52
|
+
),
|
|
53
|
+
path('<int:pk>/relate/asns/',
|
|
54
|
+
ServiceRelatedASNsView.as_view(),
|
|
55
|
+
name='relate_asns',
|
|
56
|
+
),
|
|
57
|
+
path('<int:pk>/relate/route_targets/',
|
|
58
|
+
ServiceRelatedRouteTargetsView.as_view(),
|
|
59
|
+
name='relate_route_targets',
|
|
60
|
+
),
|
|
61
|
+
path('<int:pk>/relate/l2vpns/',
|
|
62
|
+
ServiceRelatedL2VPNsView.as_view(),
|
|
63
|
+
name='relate_l2vpns',
|
|
64
|
+
),
|
|
65
|
+
path('<int:pk>/relate/tunnels/',
|
|
66
|
+
ServiceRelatedTunnelsView.as_view(),
|
|
67
|
+
name='relate_tunnels',
|
|
68
|
+
),
|
|
69
|
+
path('<int:pk>/relate/virtual_machines/',
|
|
70
|
+
ServiceRelatedVirtualMachinesView.as_view(),
|
|
71
|
+
name='relate_virtual_machines',
|
|
72
|
+
),
|
|
73
|
+
]
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
from utilities.views import register_model_view
|
|
2
|
+
from netbox.views.generic import ObjectView, ObjectDeleteView, ObjectEditView, ObjectListView
|
|
3
|
+
|
|
4
|
+
from .models import Service
|
|
5
|
+
from .tables import ServiceListTable
|
|
6
|
+
from .forms import NewServiceForm
|
|
7
|
+
from .forms import (
|
|
8
|
+
ServiceRelatedDevicesForm,
|
|
9
|
+
ServiceRelatedInterfacesForm,
|
|
10
|
+
ServiceRelatedCablesForm,
|
|
11
|
+
ServiceRelatedVLANsForm,
|
|
12
|
+
ServiceRelatedPrefixesForm,
|
|
13
|
+
ServiceRelatedVRFsForm,
|
|
14
|
+
ServiceRelatedASNsForm,
|
|
15
|
+
ServiceRelatedRouteTargetsForm,
|
|
16
|
+
ServiceRelatedL2VPNsForm,
|
|
17
|
+
ServiceRelatedTunnelsForm,
|
|
18
|
+
ServiceRelatedVirtualMachinesForm
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
#
|
|
22
|
+
# GENERIC VIEWS
|
|
23
|
+
#
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@register_model_view(Service, name='view', path='', detail=True)
|
|
27
|
+
class ServiceView(ObjectView):
|
|
28
|
+
queryset = Service.objects.all()
|
|
29
|
+
template_name = 'netbox_services/service.html'
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@register_model_view(Service, name='list', path='', detail=False)
|
|
33
|
+
class ServiceListView(ObjectListView):
|
|
34
|
+
queryset = Service.objects.all()
|
|
35
|
+
table = ServiceListTable
|
|
36
|
+
template_name = 'generic/object_list.html'
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@register_model_view(Service, name='add', path='add', detail=False)
|
|
40
|
+
class ServiceAddView(ObjectEditView):
|
|
41
|
+
queryset = Service.objects.all()
|
|
42
|
+
form = NewServiceForm
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@register_model_view(Service, name='edit', detail=True)
|
|
46
|
+
class ServiceEditView(ObjectEditView):
|
|
47
|
+
queryset = Service.objects.all()
|
|
48
|
+
form = NewServiceForm
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@register_model_view(Service, name='delete', detail=True)
|
|
52
|
+
class ServiceDeleteView(ObjectDeleteView):
|
|
53
|
+
queryset = Service.objects.all()
|
|
54
|
+
|
|
55
|
+
#
|
|
56
|
+
# RELATION VIEWS
|
|
57
|
+
#
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class ServiceRelatedDevicesView(ObjectEditView):
|
|
61
|
+
queryset = Service.objects.all()
|
|
62
|
+
form = ServiceRelatedDevicesForm
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class ServiceRelatedInterfacesView(ObjectEditView):
|
|
66
|
+
queryset = Service.objects.all()
|
|
67
|
+
form = ServiceRelatedInterfacesForm
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class ServiceRelatedCablesView(ObjectEditView):
|
|
71
|
+
queryset = Service.objects.all()
|
|
72
|
+
form = ServiceRelatedCablesForm
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class ServiceRelatedVLANsView(ObjectEditView):
|
|
76
|
+
queryset = Service.objects.all()
|
|
77
|
+
form = ServiceRelatedVLANsForm
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class ServiceRelatedPrefixesView(ObjectEditView):
|
|
81
|
+
queryset = Service.objects.all()
|
|
82
|
+
form = ServiceRelatedPrefixesForm
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
class ServiceRelatedVRFsView(ObjectEditView):
|
|
86
|
+
queryset = Service.objects.all()
|
|
87
|
+
form = ServiceRelatedVRFsForm
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
class ServiceRelatedASNsView(ObjectEditView):
|
|
91
|
+
queryset = Service.objects.all()
|
|
92
|
+
form = ServiceRelatedASNsForm
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class ServiceRelatedRouteTargetsView(ObjectEditView):
|
|
96
|
+
queryset = Service.objects.all()
|
|
97
|
+
form = ServiceRelatedRouteTargetsForm
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
class ServiceRelatedL2VPNsView(ObjectEditView):
|
|
101
|
+
queryset = Service.objects.all()
|
|
102
|
+
form = ServiceRelatedL2VPNsForm
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
class ServiceRelatedTunnelsView(ObjectEditView):
|
|
106
|
+
queryset = Service.objects.all()
|
|
107
|
+
form = ServiceRelatedTunnelsForm
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
class ServiceRelatedVirtualMachinesView(ObjectEditView):
|
|
111
|
+
queryset = Service.objects.all()
|
|
112
|
+
form = ServiceRelatedVirtualMachinesForm
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: netbox-services
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: A NetBox services Plugin for Service Providers
|
|
5
|
+
Author-email: Arturo Baldo <baldoarturo@gmail.com>
|
|
6
|
+
Maintainer-email: Arturo Baldo <baldoarturo@gmail.com>
|
|
7
|
+
Project-URL: Documentation, https://github.com/baldoarturo/netbox-services/blob/main/README.md
|
|
8
|
+
Project-URL: Source, https://github.com/baldoarturo/netbox-services
|
|
9
|
+
Project-URL: Tracker, https://github.com/baldoarturo/netbox-services/issues
|
|
10
|
+
Keywords: netbox-plugin
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Natural Language :: English
|
|
14
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Requires-Python: >=3.10
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
|
|
21
|
+
# NetBox Services Plugin
|
|
22
|
+
|
|
23
|
+
This plugin extends NetBox to manage and relate business services to network resources. It introduces a `Service` model that allows you to track various service types (such as L2VPN, L3VPN, DIA, Transit, CDN, Voice) and associate them with devices, interfaces, cables, VLANs, prefixes, VRFs, ASNs, route targets, L2VPNs, tunnels, and virtual machines.
|
|
24
|
+
|
|
25
|
+
## Features
|
|
26
|
+
- Add, edit, and delete business services.
|
|
27
|
+
- Relate services to network objects (devices, interfaces, cables, VLANs, prefixes, VRFs, ASNs, route targets, L2VPNs, tunnels, virtual machines).
|
|
28
|
+
- Filter and view services in a table with all relevant fields.
|
|
29
|
+
- Custom forms and views for relating specific network objects to a service.
|
|
30
|
+
- Integrated navigation and changelog support.
|
|
31
|
+
|
|
32
|
+
## Usage
|
|
33
|
+
- Access the plugin from the NetBox navigation menu under "Business Services".
|
|
34
|
+
- Create new services and relate them to network resources.
|
|
35
|
+
- Use the detail view to see all associations for a service.
|
|
36
|
+
|
|
37
|
+

|
|
38
|
+
|
|
39
|
+
## Why
|
|
40
|
+
Because you might be looking for such a thing.
|
|
41
|
+
|
|
42
|
+
Tagging is great for simple categorization, but the NetBox Services plugin goes far beyond that by letting you model real business services and their relationships to network resources.
|
|
43
|
+
|
|
44
|
+
Instead of just tagging a device or prefix as "DIA," you can create a full DIA service—like "NW-123456" from Cogent—and link it to all relevant devices, interfaces, prefixes, VRFs, ASNs, and more.
|
|
45
|
+
|
|
46
|
+
For example, with a DIA service from Cogent (Service ID: NW-123456), you can:
|
|
47
|
+
|
|
48
|
+
- See all devices and interfaces delivering that service.
|
|
49
|
+
- Track the exact IP prefixes, VRFs, and ASNs involved.
|
|
50
|
+
- Relate cables, tunnels, and even virtual machines to the service.
|
|
51
|
+
- View and manage all these relationships in one place, with history and forms tailored to each resource.
|
|
52
|
+
|
|
53
|
+
This gives you a true service-centric view of your network, making troubleshooting, reporting, and change management much more powerful and organized than simple tagging ever could.
|
|
54
|
+
|
|
55
|
+
## Requirements
|
|
56
|
+
- NetBox 4.x or later
|
|
57
|
+
- Django 4.x or later
|
|
58
|
+
|
|
59
|
+
## Installation
|
|
60
|
+
1. Clone this repository into your NetBox `plugins` directory. You can also install it on your system / venv / coffee maker with
|
|
61
|
+
```bash
|
|
62
|
+
pip install netbox_services
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
2. Add `'netbox_services'` to the `PLUGINS` list in your NetBox configuration.
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
PLUGINS = [
|
|
69
|
+
'netbox_services'
|
|
70
|
+
],
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
3. Run migrations: `python manage.py migrate netbox_services`
|
|
74
|
+
4. Restart NetBox.
|
|
75
|
+
|
|
76
|
+
## License
|
|
77
|
+
MIT
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
netbox_services/__init__.py
|
|
4
|
+
netbox_services/filtersets.py
|
|
5
|
+
netbox_services/forms.py
|
|
6
|
+
netbox_services/models.py
|
|
7
|
+
netbox_services/navigation.py
|
|
8
|
+
netbox_services/tables.py
|
|
9
|
+
netbox_services/urls.py
|
|
10
|
+
netbox_services/views.py
|
|
11
|
+
netbox_services.egg-info/PKG-INFO
|
|
12
|
+
netbox_services.egg-info/SOURCES.txt
|
|
13
|
+
netbox_services.egg-info/dependency_links.txt
|
|
14
|
+
netbox_services.egg-info/top_level.txt
|
|
15
|
+
netbox_services/api/__init__.py
|
|
16
|
+
netbox_services/api/serializers.py
|
|
17
|
+
netbox_services/api/urls.py
|
|
18
|
+
netbox_services/api/views.py
|
|
19
|
+
netbox_services/migrations/0001_initial.py
|
|
20
|
+
netbox_services/migrations/0002_alter_service_asns_alter_service_cables_and_more.py
|
|
21
|
+
netbox_services/migrations/0003_alter_service_options_alter_service_asns_and_more.py
|
|
22
|
+
netbox_services/migrations/0004_rename_vrf_service_vrfs_alter_service_service_id.py
|
|
23
|
+
netbox_services/migrations/__init__.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = [
|
|
3
|
+
"setuptools",
|
|
4
|
+
"wheel"
|
|
5
|
+
]
|
|
6
|
+
build-backend = "setuptools.build_meta"
|
|
7
|
+
|
|
8
|
+
[project]
|
|
9
|
+
name = "netbox-services"
|
|
10
|
+
version = "0.0.1"
|
|
11
|
+
description = "A NetBox services Plugin for Service Providers"
|
|
12
|
+
requires-python = ">=3.10"
|
|
13
|
+
|
|
14
|
+
authors = [
|
|
15
|
+
{name = "Arturo Baldo", email = "baldoarturo@gmail.com"}
|
|
16
|
+
]
|
|
17
|
+
maintainers = [
|
|
18
|
+
{name = "Arturo Baldo", email = "baldoarturo@gmail.com"},
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
readme = "README.md"
|
|
22
|
+
keywords = ["netbox-plugin", ]
|
|
23
|
+
|
|
24
|
+
license = {file = "LICENSE.md"}
|
|
25
|
+
classifiers=[
|
|
26
|
+
'Development Status :: 3 - Alpha',
|
|
27
|
+
'Intended Audience :: Developers',
|
|
28
|
+
'Natural Language :: English',
|
|
29
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
30
|
+
'Programming Language :: Python :: 3.10',
|
|
31
|
+
'Programming Language :: Python :: 3.11',
|
|
32
|
+
'Programming Language :: Python :: 3.12',
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
[project.urls]
|
|
36
|
+
Documentation = "https://github.com/baldoarturo/netbox-services/blob/main/README.md"
|
|
37
|
+
Source = "https://github.com/baldoarturo/netbox-services"
|
|
38
|
+
Tracker = "https://github.com/baldoarturo/netbox-services/issues"
|
|
39
|
+
|
|
40
|
+
[tool.setuptools.packages.find]
|
|
41
|
+
exclude=["netbox_services.tests"]
|