Skip to content

Commit 3eef636

Browse files
Merge pull request #7465 from netbox-community/develop
Release v3.0.6
2 parents d9c6609 + d451f30 commit 3eef636

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+346
-320
lines changed

.github/ISSUE_TEMPLATE/bug_report.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ body:
1717
What version of NetBox are you currently running? (If you don't have access to the most
1818
recent NetBox release, consider testing on our [demo instance](https://demo.netbox.dev/)
1919
before opening a bug report to see if your issue has already been addressed.)
20-
placeholder: v3.0.5
20+
placeholder: v3.0.6
2121
validations:
2222
required: true
2323
- type: dropdown

.github/ISSUE_TEMPLATE/feature_request.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ body:
1414
attributes:
1515
label: NetBox version
1616
description: What version of NetBox are you currently running?
17-
placeholder: v3.0.5
17+
placeholder: v3.0.6
1818
validations:
1919
required: true
2020
- type: dropdown

docs/administration/housekeeping.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,13 @@ NetBox includes a `housekeeping` management command that should be run nightly.
55
* Clearing expired authentication sessions from the database
66
* Deleting changelog records older than the configured [retention time](../configuration/optional-settings.md#changelog_retention)
77

8-
This command can be invoked directly, or by using the shell script provided at `/opt/netbox/contrib/netbox-housekeeping.sh`. This script can be copied into your cron scheduler's daily jobs directory (e.g. `/etc/cron.daily`) or referenced directly within the cron configuration file.
8+
This command can be invoked directly, or by using the shell script provided at `/opt/netbox/contrib/netbox-housekeeping.sh`. This script can be linked from your cron scheduler's daily jobs directory (e.g. `/etc/cron.daily`) or referenced directly within the cron configuration file.
99

10-
The `housekeeping` command can also be run manually at any time: Running the command outside of scheduled execution times will not interfere with its operation.
10+
```shell
11+
ln -s /opt/netbox/contrib/netbox-housekeeping.sh /etc/cron.daily/netbox-housekeeping
12+
```
13+
14+
!!! note
15+
On Debian-based systems, be sure to omit the `.sh` file extension when linking to the script from within a cron directory. Otherwise, the task may not run.
16+
17+
The `housekeeping` command can also be run manually at any time: Running the command outside scheduled execution times will not interfere with its operation.

docs/installation/3-netbox.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -259,10 +259,10 @@ python3 manage.py createsuperuser
259259

260260
NetBox includes a `housekeeping` management command that handles some recurring cleanup tasks, such as clearing out old sessions and expired change records. Although this command may be run manually, it is recommended to configure a scheduled job using the system's `cron` daemon or a similar utility.
261261

262-
A shell script which invokes this command is included at `contrib/netbox-housekeeping.sh`. It can be copied to your system's daily cron task directory, or included within the crontab directly. (If installing NetBox into a nonstandard path, be sure to update the system paths within this script first.)
262+
A shell script which invokes this command is included at `contrib/netbox-housekeeping.sh`. It can be copied to or linked from your system's daily cron task directory, or included within the crontab directly. (If installing NetBox into a nonstandard path, be sure to update the system paths within this script first.)
263263

264264
```shell
265-
cp /opt/netbox/contrib/netbox-housekeeping.sh /etc/cron.daily/
265+
ln -s /opt/netbox/contrib/netbox-housekeeping.sh /etc/cron.daily/netbox-housekeeping
266266
```
267267

268268
See the [housekeeping documentation](../administration/housekeeping.md) for further details.

docs/installation/upgrading.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,10 @@ sudo systemctl restart netbox netbox-rq
111111

112112
## Verify Housekeeping Scheduling
113113

114-
If upgrading from a release prior to NetBox v3.0, check that a cron task (or similar scheduled process) has been configured to run NetBox's nightly housekeeping command. A shell script which invokes this command is included at `contrib/netbox-housekeeping.sh`. It can be copied to your system's daily cron task directory, or included within the crontab directly. (If NetBox has been installed in a nonstandard path, be sure to update the system paths within this script first.)
114+
If upgrading from a release prior to NetBox v3.0, check that a cron task (or similar scheduled process) has been configured to run NetBox's nightly housekeeping command. A shell script which invokes this command is included at `contrib/netbox-housekeeping.sh`. It can be linked from your system's daily cron task directory, or included within the crontab directly. (If NetBox has been installed in a nonstandard path, be sure to update the system paths within this script first.)
115115

116116
```shell
117-
cp /opt/netbox/contrib/netbox-housekeeping.sh /etc/cron.daily/
117+
ln -s /opt/netbox/contrib/netbox-housekeeping.sh /etc/cron.daily/netbox-housekeeping
118118
```
119119

120120
See the [housekeeping documentation](../administration/housekeeping.md) for further details.

docs/release-notes/version-3.0.md

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,24 @@
11
# NetBox v3.0
22

3+
## v3.0.6 (2021-10-06)
4+
5+
### Enhancements
6+
7+
* [#6850](https://github.com/netbox-community/netbox/issues/6850) - Default to current user when creating journal entries via REST API
8+
* [#6955](https://github.com/netbox-community/netbox/issues/6955) - Include type, ID, and slug on object view
9+
* [#7394](https://github.com/netbox-community/netbox/issues/7394) - Enable filtering cables by termination type & ID in REST API
10+
* [#7462](https://github.com/netbox-community/netbox/issues/7462) - Include count of assigned virtual machines under platform view
11+
12+
### Bug Fixes
13+
14+
* [#7442](https://github.com/netbox-community/netbox/issues/7442) - Fix missing actions column on user-configured tables
15+
* [#7446](https://github.com/netbox-community/netbox/issues/7446) - Fix exception when viewing a large number of child IPs within a prefix
16+
* [#7455](https://github.com/netbox-community/netbox/issues/7455) - Fix site/provider network validation for circuit termination API serializer
17+
* [#7459](https://github.com/netbox-community/netbox/issues/7459) - Pre-populate location data when adding a device to a rack
18+
* [#7460](https://github.com/netbox-community/netbox/issues/7460) - Fix filtering connections by site ID
19+
20+
---
21+
322
## v3.0.5 (2021-10-04)
423

524
### Enhancements
@@ -8,7 +27,6 @@
827
* [#6423](https://github.com/netbox-community/netbox/issues/6423) - Cache rendered REST API specifications
928
* [#6708](https://github.com/netbox-community/netbox/issues/6708) - Add image attachment support for circuits, power panels
1029
* [#7387](https://github.com/netbox-community/netbox/issues/7387) - Enable arbitrary ordering of custom scripts
11-
* [#7427](https://github.com/netbox-community/netbox/issues/7427) - Don't select hidden rows when selecting all in a table
1230

1331
### Bug Fixes
1432

@@ -23,6 +41,7 @@
2341
* [#7412](https://github.com/netbox-community/netbox/issues/7412) - Fix exception in UI when adding child device to device bay
2442
* [#7417](https://github.com/netbox-community/netbox/issues/7417) - Prevent exception when filtering objects list by invalid tag
2543
* [#7425](https://github.com/netbox-community/netbox/issues/7425) - Housekeeping command should honor zero verbosity
44+
* [#7427](https://github.com/netbox-community/netbox/issues/7427) - Don't select hidden rows when selecting all in a table
2645

2746
---
2847

netbox/circuits/api/serializers.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
from circuits.choices import CircuitStatusChoices
44
from circuits.models import *
55
from dcim.api.nested_serializers import NestedCableSerializer, NestedSiteSerializer
6-
from dcim.api.serializers import CableTerminationSerializer, ConnectedEndpointSerializer
6+
from dcim.api.serializers import CableTerminationSerializer
77
from netbox.api import ChoiceField
88
from netbox.api.serializers import (
9-
BaseModelSerializer, OrganizationalModelSerializer, PrimaryModelSerializer, WritableNestedSerializer
9+
OrganizationalModelSerializer, PrimaryModelSerializer, ValidatedModelSerializer, WritableNestedSerializer
1010
)
1111
from tenancy.api.nested_serializers import NestedTenantSerializer
1212
from .nested_serializers import *
@@ -90,11 +90,11 @@ class Meta:
9090
]
9191

9292

93-
class CircuitTerminationSerializer(BaseModelSerializer, CableTerminationSerializer):
93+
class CircuitTerminationSerializer(ValidatedModelSerializer, CableTerminationSerializer):
9494
url = serializers.HyperlinkedIdentityField(view_name='circuits-api:circuittermination-detail')
9595
circuit = NestedCircuitSerializer()
96-
site = NestedSiteSerializer(required=False)
97-
provider_network = NestedProviderNetworkSerializer(required=False)
96+
site = NestedSiteSerializer(required=False, allow_null=True)
97+
provider_network = NestedProviderNetworkSerializer(required=False, allow_null=True)
9898
cable = NestedCableSerializer(read_only=True)
9999

100100
class Meta:

netbox/circuits/tests/test_api.py

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -136,14 +136,20 @@ def setUpTestData(cls):
136136
SIDE_A = CircuitTerminationSideChoices.SIDE_A
137137
SIDE_Z = CircuitTerminationSideChoices.SIDE_Z
138138

139+
provider = Provider.objects.create(name='Provider 1', slug='provider-1')
140+
circuit_type = CircuitType.objects.create(name='Circuit Type 1', slug='circuit-type-1')
141+
139142
sites = (
140143
Site(name='Site 1', slug='site-1'),
141144
Site(name='Site 2', slug='site-2'),
142145
)
143146
Site.objects.bulk_create(sites)
144147

145-
provider = Provider.objects.create(name='Provider 1', slug='provider-1')
146-
circuit_type = CircuitType.objects.create(name='Circuit Type 1', slug='circuit-type-1')
148+
provider_networks = (
149+
ProviderNetwork(provider=provider, name='Provider Network 1'),
150+
ProviderNetwork(provider=provider, name='Provider Network 2'),
151+
)
152+
ProviderNetwork.objects.bulk_create(provider_networks)
147153

148154
circuits = (
149155
Circuit(cid='Circuit 1', provider=provider, type=circuit_type),
@@ -153,24 +159,24 @@ def setUpTestData(cls):
153159
Circuit.objects.bulk_create(circuits)
154160

155161
circuit_terminations = (
156-
CircuitTermination(circuit=circuits[0], site=sites[0], term_side=SIDE_A),
157-
CircuitTermination(circuit=circuits[0], site=sites[1], term_side=SIDE_Z),
158-
CircuitTermination(circuit=circuits[1], site=sites[0], term_side=SIDE_A),
159-
CircuitTermination(circuit=circuits[1], site=sites[1], term_side=SIDE_Z),
162+
CircuitTermination(circuit=circuits[0], term_side=SIDE_A, site=sites[0]),
163+
CircuitTermination(circuit=circuits[0], term_side=SIDE_Z, provider_network=provider_networks[0]),
164+
CircuitTermination(circuit=circuits[1], term_side=SIDE_A, site=sites[1]),
165+
CircuitTermination(circuit=circuits[1], term_side=SIDE_Z, provider_network=provider_networks[1]),
160166
)
161167
CircuitTermination.objects.bulk_create(circuit_terminations)
162168

163169
cls.create_data = [
164170
{
165171
'circuit': circuits[2].pk,
166172
'term_side': SIDE_A,
167-
'site': sites[1].pk,
173+
'site': sites[0].pk,
168174
'port_speed': 200000,
169175
},
170176
{
171177
'circuit': circuits[2].pk,
172178
'term_side': SIDE_Z,
173-
'site': sites[1].pk,
179+
'provider_network': provider_networks[0].pk,
174180
'port_speed': 200000,
175181
},
176182
]

netbox/dcim/filtersets.py

Lines changed: 56 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@
1010
from tenancy.models import Tenant
1111
from utilities.choices import ColorChoices
1212
from utilities.filters import (
13-
MultiValueCharFilter, MultiValueMACAddressFilter, MultiValueNumberFilter, TreeNodeMultipleChoiceFilter,
13+
ContentTypeFilter, MultiValueCharFilter, MultiValueMACAddressFilter, MultiValueNumberFilter,
14+
TreeNodeMultipleChoiceFilter,
1415
)
1516
from virtualization.models import Cluster
1617
from .choices import *
1718
from .constants import *
1819
from .models import *
1920

20-
2121
__all__ = (
2222
'CableFilterSet',
2323
'CableTerminationFilterSet',
@@ -1184,6 +1184,10 @@ class CableFilterSet(PrimaryModelFilterSet):
11841184
method='search',
11851185
label='Search',
11861186
)
1187+
termination_a_type = ContentTypeFilter()
1188+
termination_a_id = MultiValueNumberFilter()
1189+
termination_b_type = ContentTypeFilter()
1190+
termination_b_id = MultiValueNumberFilter()
11871191
type = django_filters.MultipleChoiceFilter(
11881192
choices=CableTypeChoices
11891193
)
@@ -1228,7 +1232,7 @@ class CableFilterSet(PrimaryModelFilterSet):
12281232

12291233
class Meta:
12301234
model = Cable
1231-
fields = ['id', 'label', 'length', 'length_unit']
1235+
fields = ['id', 'label', 'length', 'length_unit', 'termination_a_id', 'termination_b_id']
12321236

12331237
def search(self, queryset, name, value):
12341238
if not value.strip():
@@ -1243,73 +1247,6 @@ def filter_device(self, queryset, name, value):
12431247
return queryset
12441248

12451249

1246-
class ConnectionFilterSet(BaseFilterSet):
1247-
1248-
def filter_site(self, queryset, name, value):
1249-
if not value.strip():
1250-
return queryset
1251-
return queryset.filter(device__site__slug=value)
1252-
1253-
def filter_device(self, queryset, name, value):
1254-
if not value:
1255-
return queryset
1256-
return queryset.filter(**{f'{name}__in': value})
1257-
1258-
1259-
class ConsoleConnectionFilterSet(ConnectionFilterSet):
1260-
site = django_filters.CharFilter(
1261-
method='filter_site',
1262-
label='Site (slug)',
1263-
)
1264-
device_id = MultiValueNumberFilter(
1265-
method='filter_device'
1266-
)
1267-
device = MultiValueCharFilter(
1268-
method='filter_device',
1269-
field_name='device__name'
1270-
)
1271-
1272-
class Meta:
1273-
model = ConsolePort
1274-
fields = ['name']
1275-
1276-
1277-
class PowerConnectionFilterSet(ConnectionFilterSet):
1278-
site = django_filters.CharFilter(
1279-
method='filter_site',
1280-
label='Site (slug)',
1281-
)
1282-
device_id = MultiValueNumberFilter(
1283-
method='filter_device'
1284-
)
1285-
device = MultiValueCharFilter(
1286-
method='filter_device',
1287-
field_name='device__name'
1288-
)
1289-
1290-
class Meta:
1291-
model = PowerPort
1292-
fields = ['name']
1293-
1294-
1295-
class InterfaceConnectionFilterSet(ConnectionFilterSet):
1296-
site = django_filters.CharFilter(
1297-
method='filter_site',
1298-
label='Site (slug)',
1299-
)
1300-
device_id = MultiValueNumberFilter(
1301-
method='filter_device'
1302-
)
1303-
device = MultiValueCharFilter(
1304-
method='filter_device',
1305-
field_name='device__name'
1306-
)
1307-
1308-
class Meta:
1309-
model = Interface
1310-
fields = []
1311-
1312-
13131250
class PowerPanelFilterSet(PrimaryModelFilterSet):
13141251
q = django_filters.CharFilter(
13151252
method='search',
@@ -1441,3 +1378,52 @@ def search(self, queryset, name, value):
14411378
Q(comments__icontains=value)
14421379
)
14431380
return queryset.filter(qs_filter)
1381+
1382+
1383+
#
1384+
# Connection filter sets
1385+
#
1386+
1387+
class ConnectionFilterSet(BaseFilterSet):
1388+
site_id = MultiValueNumberFilter(
1389+
method='filter_connections',
1390+
field_name='device__site_id'
1391+
)
1392+
site = MultiValueCharFilter(
1393+
method='filter_connections',
1394+
field_name='device__site__slug'
1395+
)
1396+
device_id = MultiValueNumberFilter(
1397+
method='filter_connections',
1398+
field_name='device_id'
1399+
)
1400+
device = MultiValueCharFilter(
1401+
method='filter_connections',
1402+
field_name='device__name'
1403+
)
1404+
1405+
def filter_connections(self, queryset, name, value):
1406+
if not value:
1407+
return queryset
1408+
return queryset.filter(**{f'{name}__in': value})
1409+
1410+
1411+
class ConsoleConnectionFilterSet(ConnectionFilterSet):
1412+
1413+
class Meta:
1414+
model = ConsolePort
1415+
fields = ['name']
1416+
1417+
1418+
class PowerConnectionFilterSet(ConnectionFilterSet):
1419+
1420+
class Meta:
1421+
model = PowerPort
1422+
fields = ['name']
1423+
1424+
1425+
class InterfaceConnectionFilterSet(ConnectionFilterSet):
1426+
1427+
class Meta:
1428+
model = Interface
1429+
fields = []

netbox/dcim/svg.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -132,14 +132,18 @@ def _draw_device_rear(self, drawing, device, start, end, text):
132132

133133
@staticmethod
134134
def _draw_empty(drawing, rack, start, end, text, id_, face_id, class_, reservation):
135+
link_url = '{}?{}'.format(
136+
reverse('dcim:device_add'),
137+
urlencode({
138+
'site': rack.site.pk,
139+
'location': rack.location.pk if rack.location else '',
140+
'rack': rack.pk,
141+
'face': face_id,
142+
'position': id_
143+
})
144+
)
135145
link = drawing.add(
136-
drawing.a(
137-
href='{}?{}'.format(
138-
reverse('dcim:device_add'),
139-
urlencode({'rack': rack.pk, 'site': rack.site.pk, 'face': face_id, 'position': id_})
140-
),
141-
target='_top'
142-
)
146+
drawing.a(href=link_url, target='_top')
143147
)
144148
if reservation:
145149
link.set_desc('{} — {} · {}'.format(

0 commit comments

Comments
 (0)