Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release v3.5.1 #12507

Merged
merged 46 commits into from
May 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
25dc7e2
PRVB
jeremystretch Apr 27, 2023
aabaeec
Add ObjectChange as a valid option for ObjectListWidget and ObjectCou…
kkthxbye-code Apr 28, 2023
6206d22
Fix the filtervar being set to site_id instead of site in SiteView re…
kkthxbye-code May 1, 2023
528fb21
Mark provider_account as not required in API and bulk import
kkthxbye-code May 1, 2023
3fc7c0e
Merge pull request #12407 from kkthxbye-code/12396-fix-provideraccount
jeremystretch May 1, 2023
f86f4f9
Merge pull request #12406 from kkthxbye-code/12405-fix-related-vlangroup
jeremystretch May 1, 2023
a0f0b29
Merge pull request #12382 from kkthxbye-code/12380-widget-fix-missing-ct
jeremystretch May 1, 2023
47f3023
Fixes #12412: Device/VM interface MAC addresses can be nullified via …
jeremystretch May 1, 2023
139ef7e
Fixes #12395: Fix "create & add another" action for objects with cust…
jeremystretch May 1, 2023
8cede0d
Changelog for #12380, #12395, #12396, #12405, #12412
jeremystretch May 1, 2023
261f5e4
Fixes #12415: Pin rq to v1.13.0 to fix ImportError exception from dja…
jeremystretch May 1, 2023
9319cff
Fixes #12384: Add a three-second timeout for RSS reader widget
jeremystretch May 1, 2023
1952707
Fixes #12401: Support the creation of front ports without a pre-popul…
jeremystretch May 1, 2023
20f0464
Fix OpanAPI schema base path
jeremystretch May 1, 2023
3bdbf67
Update examples to reflect obj rename to object
jzinkweg May 2, 2023
2099cd0
#12415: Bump django-rq to v2.8.0
jeremystretch May 2, 2023
cc3b95b
Fixes #12400: Validate default values for object and multi-object cus…
jeremystretch May 2, 2023
a566a56
fixes RelatedObjectDoesNotExist #12367
abhi1693 Apr 27, 2023
fbcf4c2
12436 remove add button from contactassignment list view
arthanson May 2, 2023
7aa8434
Changelog for #12367, #12410, #12436
jeremystretch May 2, 2023
b14a514
Closes 10759: Enable markdown support for custom field descriptions (…
decoupca May 2, 2023
24650d9
11422 add power-panel-name to quick search of power feeds
arthanson May 2, 2023
78ec3a6
11504 add rack filter to elevation
arthanson May 2, 2023
5036020
12433 update object list widget to correctly parameterize urls (#12434)
arthanson May 3, 2023
01fa6e2
Changelog for #10759, #11422, #11504, #12433
jeremystretch May 3, 2023
2c75687
Fix broken links
jeremystretch May 4, 2023
4df517e
Fix #12464: Only set username, password for HTTP/s (#12482)
tobiasge May 4, 2023
93b912c
Adds ENGINE to database config (#12458)
abhi1693 May 4, 2023
25142e0
Adds housekeeping systemd files (#12457)
abhi1693 May 4, 2023
ea8a013
Adds module status to module bay table (#12455)
abhi1693 May 4, 2023
46914d9
Fixes: #10757 - Change IP interface assignment to use new selector (#…
DanSheps May 4, 2023
683ef30
12363 update paragraph spacing on journal table (#12435)
arthanson May 4, 2023
3eba65b
Changelog for #10757, #11652, #11791, #11190, #12363, #12464
jeremystretch May 4, 2023
f3826e6
fix runscript command
arthanson May 4, 2023
ab69faa
Fix #12483: Using mutable dulwich configuration
tobiasge May 4, 2023
a96b76a
Fixes #12496: Remove account field from provider template
May 5, 2023
9d62174
Fix #12245 - Add WLAN to InterfaceBulkEditForm
stuntguy3000 May 5, 2023
abdcfde
Adds description to elevation device tooltip (#12488)
abhi1693 May 5, 2023
7a38f60
Fixes: #11715 - Fix Parent Prefix table display (#12448)
DanSheps May 5, 2023
9909213
12416 warning for missing script file (#12456)
arthanson May 5, 2023
4234670
Adds image attachment list view (#12487)
abhi1693 May 5, 2023
ca0e7be
Adds bulk import for journal entry (#12485)
abhi1693 May 5, 2023
42c80f6
Changelog for #11715, #11801, #11932, #12122, #12245, #12416, #12476,…
jeremystretch May 5, 2023
a29a07e
Fixes #12463: Fix the association of completed jobs with reports & sc…
jeremystretch May 5, 2023
6794742
Release v3.5.1
jeremystretch May 5, 2023
56a4d03
Formatting fix
jeremystretch May 5, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/bug_report.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ body:
attributes:
label: NetBox version
description: What version of NetBox are you currently running?
placeholder: v3.5.0
placeholder: v3.5.1
validations:
required: true
- type: dropdown
Expand Down
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/feature_request.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ body:
attributes:
label: NetBox version
description: What version of NetBox are you currently running?
placeholder: v3.5.0
placeholder: v3.5.1
validations:
required: true
- type: dropdown
Expand Down
17 changes: 17 additions & 0 deletions contrib/netbox-housekeeping.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[Unit]
Description=NetBox Housekeeping Service
Documentation=https://docs.netbox.dev/
After=network-online.target
Wants=network-online.target

[Service]
Type=simple

User=netbox
Group=netbox
WorkingDirectory=/opt/netbox

ExecStart=/opt/netbox/venv/bin/python /opt/netbox/netbox/manage.py housekeeping

[Install]
WantedBy=multi-user.target
13 changes: 13 additions & 0 deletions contrib/netbox-housekeeping.timer
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[Unit]
Description=NetBox Housekeeping Timer
Documentation=https://docs.netbox.dev/
After=network-online.target
Wants=network-online.target

[Timer]
OnCalendar=daily
AccuracySec=1h
Persistent=true

[Install]
WantedBy=multi-user.target
34 changes: 32 additions & 2 deletions docs/administration/housekeeping.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@ NetBox includes a `housekeeping` management command that should be run nightly.
* Deleting job result records older than the configured [retention time](../configuration/miscellaneous.md#job_retention)
* Check for new NetBox releases (if [`RELEASE_CHECK_URL`](../configuration/miscellaneous.md#release_check_url) is set)

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.
This command can be invoked directly, or by using the shell script provided at `/opt/netbox/contrib/netbox-housekeeping.sh`.

## Scheduling

### Using Cron

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.

```shell
sudo ln -s /opt/netbox/contrib/netbox-housekeeping.sh /etc/cron.daily/netbox-housekeeping
Expand All @@ -16,4 +22,28 @@ sudo ln -s /opt/netbox/contrib/netbox-housekeeping.sh /etc/cron.daily/netbox-hou
!!! note
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.

The `housekeeping` command can also be run manually at any time: Running the command outside scheduled execution times will not interfere with its operation.
### Using Systemd

First, create symbolic links for the systemd service and timer files. Link the existing service and timer files from the `/opt/netbox/contrib/` directory to the `/etc/systemd/system/` directory:

```bash
sudo ln -s /opt/netbox/contrib/netbox-housekeeping.service /etc/systemd/system/netbox-housekeeping.service
sudo ln -s /opt/netbox/contrib/netbox-housekeeping.timer /etc/systemd/system/netbox-housekeeping.timer
```

Then, reload the systemd configuration and enable the timer to start automatically at boot:

```bash
sudo systemctl daemon-reload
sudo systemctl enable --now netbox-housekeeping.timer
```

Check the status of your timer by running:

```bash
sudo systemctl list-timers --all
```

This command will show a list of all timers, including your `netbox-housekeeping.timer`. Make sure the timer is active and properly scheduled.

That's it! Your NetBox housekeeping service is now configured to run daily using systemd.
5 changes: 5 additions & 0 deletions docs/configuration/required-parameters.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,13 @@ NetBox requires access to a PostgreSQL 11 or later database service to store dat
* `HOST` - Name or IP address of the database server (use `localhost` if running locally)
* `PORT` - TCP port of the PostgreSQL service; leave blank for default port (TCP/5432)
* `CONN_MAX_AGE` - Lifetime of a [persistent database connection](https://docs.djangoproject.com/en/stable/ref/databases/#persistent-connections), in seconds (300 is the default)
* `ENGINE` - The database backend to use; must be a PostgreSQL-compatible backend (e.g. `django.db.backends.postgresql`)

Example:

```python
DATABASE = {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'netbox', # Database name
'USER': 'netbox', # PostgreSQL username
'PASSWORD': 'J5brHrAXFLQSif0K', # PostgreSQL password
Expand All @@ -50,6 +52,9 @@ DATABASE = {
!!! note
NetBox supports all PostgreSQL database options supported by the underlying Django framework. For a complete list of available parameters, please see [the Django documentation](https://docs.djangoproject.com/en/stable/ref/settings/#databases).

!!! warning
Make sure to use a PostgreSQL-compatible backend for the ENGINE setting. If you don't specify an ENGINE, the default will be django.db.backends.postgresql.

---

## REDIS
Expand Down
8 changes: 4 additions & 4 deletions docs/customization/custom-links.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

Custom links allow users to display arbitrary hyperlinks to external content within NetBox object views. These are helpful for cross-referencing related records in systems outside NetBox. For example, you might create a custom link on the device view which links to the current device in a Network Monitoring System (NMS).

Custom links are created by navigating to Customization > Custom Links. Each link is associated with a particular NetBox object type (site, device, prefix, etc.) and will be displayed on relevant views. Each link has display text and a URL, and data from the NetBox item being viewed can be included in the link using [Jinja2 template code](https://jinja2docs.readthedocs.io/en/stable/) through the variable `obj`, and custom fields through `obj.cf`.
Custom links are created by navigating to Customization > Custom Links. Each link is associated with a particular NetBox object type (site, device, prefix, etc.) and will be displayed on relevant views. Each link has display text and a URL, and data from the NetBox item being viewed can be included in the link using [Jinja2 template code](https://jinja2docs.readthedocs.io/en/stable/) through the variable `object`, and custom fields through `object.cf`.

For example, you might define a link like this:

* Text: `View NMS`
* URL: `https://nms.example.com/nodes/?name={{ obj.name }}`
* URL: `https://nms.example.com/nodes/?name={{ object.name }}`

When viewing a device named Router4, this link would render as:

Expand Down Expand Up @@ -43,15 +43,15 @@ Only links which render with non-empty text are included on the page. You can em
For example, if you only want to display a link for active devices, you could set the link text to

```jinja2
{% if obj.status == 'active' %}View NMS{% endif %}
{% if object.status == 'active' %}View NMS{% endif %}
```

The link will not appear when viewing a device with any status other than "active."

As another example, if you wanted to show only devices belonging to a certain manufacturer, you could do something like this:

```jinja2
{% if obj.device_type.manufacturer.name == 'Cisco' %}View NMS{% endif %}
{% if object.device_type.manufacturer.name == 'Cisco' %}View NMS{% endif %}
```

The link will only appear when viewing a device with a manufacturer name of "Cisco."
Expand Down
2 changes: 1 addition & 1 deletion docs/development/models.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ These are considered the "core" application models which are used to model netwo

* [circuits.Circuit](../models/circuits/circuit.md)
* [circuits.Provider](../models/circuits/provider.md)
* [circuits.ProviderAccount](../models/circuits/provideracount.md)
* [circuits.ProviderAccount](../models/circuits/provideraccount.md)
* [circuits.ProviderNetwork](../models/circuits/providernetwork.md)
* [core.DataSource](../models/core/datasource.md)
* [dcim.Cable](../models/dcim/cable.md)
Expand Down
2 changes: 0 additions & 2 deletions docs/models/dcim/platform.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ A platform defines the type of software running on a [device](./device.md) or [v

Platforms may optionally be limited by [manufacturer](./manufacturer.md): If a platform is assigned to a particular manufacturer, it can only be assigned to devices with a type belonging to that manufacturer.

The platform model is also used to indicate which [NAPALM driver](../../integrations/napalm.md) (if any) and any associated arguments NetBox should use when connecting to a remote device. The name of the driver along with optional parameters are stored with the platform.

The assignment of platforms to devices is an optional feature, and may be disregarded if not desired.

## Fields
Expand Down
42 changes: 42 additions & 0 deletions docs/release-notes/version-3.5.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,47 @@
# NetBox v3.5

## v3.5.1 (2023-05-05)

### Enhancements

* [#10759](https://github.com/netbox-community/netbox/issues/10759) - Support Markdown rendering for custom field descriptions
* [#11190](https://github.com/netbox-community/netbox/issues/11190) - Including systemd service & timer configurations for housekeeping tasks
* [#11422](https://github.com/netbox-community/netbox/issues/11422) - Match on power panel name when searching for power feeds
* [#11504](https://github.com/netbox-community/netbox/issues/11504) - Add filter to select individual racks under rack elevations view
* [#11652](https://github.com/netbox-community/netbox/issues/11652) - Add a module status column to module bay tables
* [#11791](https://github.com/netbox-community/netbox/issues/11791) - Enable configuration of custom database backend via `ENGINE` parameter
* [#11801](https://github.com/netbox-community/netbox/issues/11801) - Include device description within rack elevation tooltip
* [#11932](https://github.com/netbox-community/netbox/issues/11932) - Introduce a list view for image attachments, orderable by date and other attributes
* [#12122](https://github.com/netbox-community/netbox/issues/12122) - Enable bulk import oj journal entries
* [#12245](https://github.com/netbox-community/netbox/issues/12245) - Enable the assignment of wireless LANs to interfaces under bulk edit

### Bug Fixes

* [#10757](https://github.com/netbox-community/netbox/issues/10757) - Simplify IP address interface and NAT IP assignment form fields to avoid confusion
* [#11715](https://github.com/netbox-community/netbox/issues/11715) - Prefix within a VRF should list global prefixes as parents only if they are containers
* [#12363](https://github.com/netbox-community/netbox/issues/12363) - Fix whitespace for paragraph elements in Markdown-rendered table columns
* [#12367](https://github.com/netbox-community/netbox/issues/12367) - Fix `RelatedObjectDoesNotExist` exception under certain conditions (regression from #11550)
* [#12380](https://github.com/netbox-community/netbox/issues/12380) - Allow selecting object change as model under object list widget configuration
* [#12384](https://github.com/netbox-community/netbox/issues/12384) - Add a three-second timeout for RSS reader widget
* [#12395](https://github.com/netbox-community/netbox/issues/12395) - Fix "create & add another" action for objects with custom fields
* [#12396](https://github.com/netbox-community/netbox/issues/12396) - Provider account should not be a required field in REST API serializer
* [#12400](https://github.com/netbox-community/netbox/issues/12400) - Validate default values for object and multi-object custom fields
* [#12401](https://github.com/netbox-community/netbox/issues/12401) - Support the creation of front ports without a pre-populated device ID
* [#12405](https://github.com/netbox-community/netbox/issues/12405) - Fix filtering for VLAN groups displayed under site view
* [#12410](https://github.com/netbox-community/netbox/issues/12410) - Fix base path for OpenAPI schema (fixes Swagger UI requests)
* [#12416](https://github.com/netbox-community/netbox/issues/12416) - Fix `FileNotFoundError` exception when a managed script file is missing from disk
* [#12412](https://github.com/netbox-community/netbox/issues/12412) - Device/VM interface MAC addresses can be nullified via REST API
* [#12415](https://github.com/netbox-community/netbox/issues/12415) - Fix `ImportError` exception when running RQ worker
* [#12433](https://github.com/netbox-community/netbox/issues/12433) - Correct the application of URL query parameters for object list dashboard widgets
* [#12436](https://github.com/netbox-community/netbox/issues/12436) - Remove extraneous "add" button from contact assignments list
* [#12463](https://github.com/netbox-community/netbox/issues/12463) - Fix the association of completed jobs with reports & scripts in the REST API
* [#12464](https://github.com/netbox-community/netbox/issues/12464) - Apply credentials for git data source only when connecting via HTTP/S
* [#12476](https://github.com/netbox-community/netbox/issues/12476) - Fix `TypeError` exception when running the `runscript` management command
* [#12483](https://github.com/netbox-community/netbox/issues/12483) - Fix git remote data syncing when with HTTP proxies defined
* [#12496](https://github.com/netbox-community/netbox/issues/12496) - Remove obsolete account field from provider UI view

---

## v3.5.0 (2023-04-27)

### Breaking Changes
Expand Down
2 changes: 1 addition & 1 deletion netbox/circuits/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ class Meta:
class CircuitSerializer(NetBoxModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='circuits-api:circuit-detail')
provider = NestedProviderSerializer()
provider_account = NestedProviderAccountSerializer()
provider_account = NestedProviderAccountSerializer(required=False, allow_null=True)
status = ChoiceField(choices=CircuitStatusChoices, required=False)
type = NestedCircuitTypeSerializer()
tenant = NestedTenantSerializer(required=False, allow_null=True)
Expand Down
3 changes: 2 additions & 1 deletion netbox/circuits/forms/bulk_import.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ class CircuitImportForm(NetBoxModelImportForm):
provider_account = CSVModelChoiceField(
queryset=ProviderAccount.objects.all(),
to_field_name='name',
help_text=_('Assigned provider account')
help_text=_('Assigned provider account'),
required=False
)
type = CSVModelChoiceField(
queryset=CircuitType.objects.all(),
Expand Down
15 changes: 2 additions & 13 deletions netbox/core/api/schema.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,12 @@
import re
import typing

from drf_spectacular.extensions import (
OpenApiSerializerFieldExtension,
OpenApiViewExtension,
)
from drf_spectacular.extensions import OpenApiSerializerFieldExtension
from drf_spectacular.openapi import AutoSchema
from drf_spectacular.plumbing import (
ComponentRegistry,
ResolvedComponent,
build_basic_type,
build_choice_field,
build_media_type_object,
build_object_type,
get_doc,
is_serializer,
build_basic_type, build_choice_field, build_media_type_object, build_object_type, get_doc,
)
from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import extend_schema
from rest_framework.relations import ManyRelatedField

from netbox.api.fields import ChoiceField, SerializedPKRelatedField
Expand Down
35 changes: 23 additions & 12 deletions netbox/core/data_backends.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from django.conf import settings
from django.utils.translation import gettext as _
from dulwich import porcelain
from dulwich.config import StackedConfig
from dulwich.config import ConfigDict

from netbox.registry import registry
from .choices import DataSourceTypeChoices
Expand All @@ -31,6 +31,7 @@ def register_backend(name):
"""
Decorator for registering a DataBackend class.
"""

def _wrapper(cls):
registry['data_backends'][name] = cls
return cls
Expand All @@ -56,7 +57,6 @@ def fetch(self):

@register_backend(DataSourceTypeChoices.LOCAL)
class LocalBackend(DataBackend):

@contextmanager
def fetch(self):
logger.debug(f"Data source type is local; skipping fetch")
Expand All @@ -71,12 +71,14 @@ class GitBackend(DataBackend):
'username': forms.CharField(
required=False,
label=_('Username'),
widget=forms.TextInput(attrs={'class': 'form-control'})
widget=forms.TextInput(attrs={'class': 'form-control'}),
help_text=_("Only used for cloning with HTTP / HTTPS"),
),
'password': forms.CharField(
required=False,
label=_('Password'),
widget=forms.TextInput(attrs={'class': 'form-control'})
widget=forms.TextInput(attrs={'class': 'form-control'}),
help_text=_("Only used for cloning with HTTP / HTTPS"),
),
'branch': forms.CharField(
required=False,
Expand All @@ -89,21 +91,30 @@ class GitBackend(DataBackend):
def fetch(self):
local_path = tempfile.TemporaryDirectory()

username = self.params.get('username')
password = self.params.get('password')
branch = self.params.get('branch')
config = StackedConfig.default()
config = ConfigDict()
clone_args = {
"branch": self.params.get('branch'),
"config": config,
"depth": 1,
"errstream": porcelain.NoneStream(),
"quiet": True,
}

if self.url_scheme in ('http', 'https'):
clone_args.update(
{
"username": self.params.get('username'),
"password": self.params.get('password'),
}
)

if settings.HTTP_PROXIES and self.url_scheme in ('http', 'https'):
if proxy := settings.HTTP_PROXIES.get(self.url_scheme):
config.set("http", "proxy", proxy)

logger.debug(f"Cloning git repo: {self.url}")
try:
porcelain.clone(
self.url, local_path.name, depth=1, branch=branch, username=username, password=password,
config=config, quiet=True, errstream=porcelain.NoneStream()
)
porcelain.clone(self.url, local_path.name, **clone_args)
except BaseException as e:
raise SyncError(f"Fetching remote data failed ({type(e).__name__}): {e}")

Expand Down
6 changes: 5 additions & 1 deletion netbox/dcim/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -904,7 +904,11 @@ class InterfaceSerializer(NetBoxModelSerializer, CabledObjectSerializer, Connect
)
count_ipaddresses = serializers.IntegerField(read_only=True)
count_fhrp_groups = serializers.IntegerField(read_only=True)
mac_address = serializers.CharField(required=False, default=None)
mac_address = serializers.CharField(
required=False,
default=None,
allow_null=True
)
wwn = serializers.CharField(required=False, default=None)

class Meta:
Expand Down
1 change: 1 addition & 0 deletions netbox/dcim/filtersets.py
Original file line number Diff line number Diff line change
Expand Up @@ -1900,6 +1900,7 @@ def search(self, queryset, name, value):
return queryset
qs_filter = (
Q(name__icontains=value) |
Q(power_panel__name__icontains=value) |
Q(comments__icontains=value)
)
return queryset.filter(qs_filter)
Expand Down
Loading