mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-22 03:56:53 -06:00
Merge pull request #5034 from netbox-community/develop
Release v2.9.1 - 2020-08-22
This commit is contained in:
commit
848cfeb353
@ -4,8 +4,15 @@
|
|||||||
|
|
||||||
Prior to upgrading your NetBox instance, be sure to carefully review all [release notes](../../release-notes/) that have been published since your current version was released. Although the upgrade process typically does not involve additional work, certain releases may introduce breaking or backward-incompatible changes. These are called out in the release notes under the version in which the change went into effect.
|
Prior to upgrading your NetBox instance, be sure to carefully review all [release notes](../../release-notes/) that have been published since your current version was released. Although the upgrade process typically does not involve additional work, certain releases may introduce breaking or backward-incompatible changes. These are called out in the release notes under the version in which the change went into effect.
|
||||||
|
|
||||||
!!! note
|
## Update Dependencies to Required Versions
|
||||||
Beginning with version 2.8, NetBox requires Python 3.6 or later.
|
|
||||||
|
NetBox v2.9.0 and later requires the following:
|
||||||
|
|
||||||
|
| Dependency | Minimum Version |
|
||||||
|
|------------|-----------------|
|
||||||
|
| Python | 3.6 |
|
||||||
|
| PostgreSQL | 9.6 |
|
||||||
|
| Redis | 4.0 |
|
||||||
|
|
||||||
## Install the Latest Code
|
## Install the Latest Code
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ Interfaces in NetBox represent network interfaces used to exchange data with con
|
|||||||
|
|
||||||
Interfaces may be physical or virtual in nature, but only physical interfaces may be connected via cables. Cables can connect interfaces to pass-through ports, circuit terminations, or other interfaces.
|
Interfaces may be physical or virtual in nature, but only physical interfaces may be connected via cables. Cables can connect interfaces to pass-through ports, circuit terminations, or other interfaces.
|
||||||
|
|
||||||
Physical interfaces may be arranged into a link aggregation group (LAG) and associated with a parent LAG (virtual) interface. Like all virtual interfaces, LAG interfaces cannot be connected physically.
|
Physical interfaces may be arranged into a link aggregation group (LAG) and associated with a parent LAG (virtual) interface. LAG interfaces can be recursively nested to model bonding of trunk groups. Like all virtual interfaces, LAG interfaces cannot be connected physically.
|
||||||
|
|
||||||
IP addresses can be assigned to interfaces. VLANs can also be assigned to each interface as either tagged or untagged. (An interface may have only one untagged VLAN.)
|
IP addresses can be assigned to interfaces. VLANs can also be assigned to each interface as either tagged or untagged. (An interface may have only one untagged VLAN.)
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ Each IP address can also be assigned an operational status and a functional role
|
|||||||
* Reserved
|
* Reserved
|
||||||
* Deprecated
|
* Deprecated
|
||||||
* DHCP
|
* DHCP
|
||||||
|
* SLAAC (IPv6 Stateless Address Autoconfiguration)
|
||||||
|
|
||||||
Roles are used to indicate some special attribute of an IP address; for example, use as a loopback or as the the virtual IP for a VRRP group. (Note that functional roles are conceptual in nature, and thus cannot be customized by the user.) Available roles include:
|
Roles are used to indicate some special attribute of an IP address; for example, use as a loopback or as the the virtual IP for a VRRP group. (Note that functional roles are conceptual in nature, and thus cannot be customized by the user.) Available roles include:
|
||||||
|
|
||||||
|
@ -1,7 +1,20 @@
|
|||||||
# NetBox v2.9
|
# NetBox v2.9
|
||||||
|
|
||||||
|
## v2.9.1 (2020-08-22)
|
||||||
|
|
||||||
|
### Enhancements
|
||||||
|
|
||||||
|
* [#4540](https://github.com/netbox-community/netbox/issues/4540) - Add IP address status type for SLAAC
|
||||||
|
* [#4814](https://github.com/netbox-community/netbox/issues/4814) - Allow nested LAG interfaces
|
||||||
|
* [#4991](https://github.com/netbox-community/netbox/issues/4991) - Add Python and NetBox versions to error page
|
||||||
|
* [#5033](https://github.com/netbox-community/netbox/issues/5033) - Support backward compatibility for `REMOTE_AUTH_BACKEND` configuration parameter
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## v2.9.0 (2020-08-21)
|
## v2.9.0 (2020-08-21)
|
||||||
|
|
||||||
|
**Note:** Redis 4.0 or later is required for this release.
|
||||||
|
|
||||||
### New Features
|
### New Features
|
||||||
|
|
||||||
#### Object-Based Permissions ([#554](https://github.com/netbox-community/netbox/issues/554))
|
#### Object-Based Permissions ([#554](https://github.com/netbox-community/netbox/issues/554))
|
||||||
@ -56,7 +69,8 @@ Two new REST API endpoints have been added to facilitate the retrieval and manip
|
|||||||
|
|
||||||
### Configuration Changes
|
### Configuration Changes
|
||||||
|
|
||||||
* If in use, LDAP authentication must be enabled by setting `REMOTE_AUTH_BACKEND` to `'netbox.authentication.LDAPBackend'`. (LDAP configuration parameters in `ldap_config.py` remain unchanged.)
|
* If using NetBox's built-in remote authentication backend, update `REMOTE_AUTH_BACKEND` to `'netbox.authentication.RemoteUserBackend'`, as the authentication class has moved.
|
||||||
|
* If using LDAP authentication, set `REMOTE_AUTH_BACKEND` to `'netbox.authentication.LDAPBackend'`. (LDAP configuration parameters in `ldap_config.py` remain unchanged.)
|
||||||
* `REMOTE_AUTH_DEFAULT_PERMISSIONS` now takes a dictionary rather than a list. This is a mapping of permission names to a dictionary of constraining attributes, or `None`. For example, `['dcim.add_site', 'dcim.change_site']` would become `{'dcim.add_site': None, 'dcim.change_site': None}`.
|
* `REMOTE_AUTH_DEFAULT_PERMISSIONS` now takes a dictionary rather than a list. This is a mapping of permission names to a dictionary of constraining attributes, or `None`. For example, `['dcim.add_site', 'dcim.change_site']` would become `{'dcim.add_site': None, 'dcim.change_site': None}`.
|
||||||
|
|
||||||
### REST API Changes
|
### REST API Changes
|
||||||
|
@ -76,6 +76,7 @@ nav:
|
|||||||
- User Preferences: 'development/user-preferences.md'
|
- User Preferences: 'development/user-preferences.md'
|
||||||
- Release Checklist: 'development/release-checklist.md'
|
- Release Checklist: 'development/release-checklist.md'
|
||||||
- Release Notes:
|
- Release Notes:
|
||||||
|
- Version 2.9: 'release-notes/version-2.9.md'
|
||||||
- Version 2.8: 'release-notes/version-2.8.md'
|
- Version 2.8: 'release-notes/version-2.8.md'
|
||||||
- Version 2.7: 'release-notes/version-2.7.md'
|
- Version 2.7: 'release-notes/version-2.7.md'
|
||||||
- Version 2.6: 'release-notes/version-2.6.md'
|
- Version 2.6: 'release-notes/version-2.6.md'
|
||||||
|
@ -2686,7 +2686,10 @@ class InterfaceForm(InterfaceCommonForm, BootstrapMixin, forms.ModelForm):
|
|||||||
device_query = Q(device=device)
|
device_query = Q(device=device)
|
||||||
if device.virtual_chassis:
|
if device.virtual_chassis:
|
||||||
device_query |= Q(device__virtual_chassis=device.virtual_chassis)
|
device_query |= Q(device__virtual_chassis=device.virtual_chassis)
|
||||||
self.fields['lag'].queryset = Interface.objects.filter(device_query, type=InterfaceTypeChoices.TYPE_LAG)
|
self.fields['lag'].queryset = Interface.objects.filter(
|
||||||
|
device_query,
|
||||||
|
type=InterfaceTypeChoices.TYPE_LAG
|
||||||
|
).exclude(pk=self.instance.pk)
|
||||||
|
|
||||||
# Add current site to VLANs query params
|
# Add current site to VLANs query params
|
||||||
self.fields['untagged_vlan'].widget.add_query_param('site_id', device.site.pk)
|
self.fields['untagged_vlan'].widget.add_query_param('site_id', device.site.pk)
|
||||||
|
@ -702,18 +702,12 @@ class Interface(CableTermination, ComponentModel, BaseInterface):
|
|||||||
})
|
})
|
||||||
|
|
||||||
# A virtual interface cannot have a parent LAG
|
# A virtual interface cannot have a parent LAG
|
||||||
if self.type in NONCONNECTABLE_IFACE_TYPES and self.lag is not None:
|
if self.type == InterfaceTypeChoices.TYPE_VIRTUAL and self.lag is not None:
|
||||||
raise ValidationError({
|
raise ValidationError({'lag': "Virtual interfaces cannot have a parent LAG interface."})
|
||||||
'lag': "{} interfaces cannot have a parent LAG interface.".format(self.get_type_display())
|
|
||||||
})
|
|
||||||
|
|
||||||
# Only a LAG can have LAG members
|
# A LAG interface cannot be its own parent
|
||||||
if self.type != InterfaceTypeChoices.TYPE_LAG and self.member_interfaces.exists():
|
if self.pk and self.lag_id == self.pk:
|
||||||
raise ValidationError({
|
raise ValidationError({'lag': "A LAG interface cannot be its own parent."})
|
||||||
'type': "Cannot change interface type; it has LAG members ({}).".format(
|
|
||||||
", ".join([iface.name for iface in self.member_interfaces.all()])
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
# Validate untagged VLAN
|
# Validate untagged VLAN
|
||||||
if self.untagged_vlan and self.untagged_vlan.site not in [self.parent.site, None]:
|
if self.untagged_vlan and self.untagged_vlan.site not in [self.parent.site, None]:
|
||||||
|
@ -41,12 +41,14 @@ class IPAddressStatusChoices(ChoiceSet):
|
|||||||
STATUS_RESERVED = 'reserved'
|
STATUS_RESERVED = 'reserved'
|
||||||
STATUS_DEPRECATED = 'deprecated'
|
STATUS_DEPRECATED = 'deprecated'
|
||||||
STATUS_DHCP = 'dhcp'
|
STATUS_DHCP = 'dhcp'
|
||||||
|
STATUS_SLAAC = 'slaac'
|
||||||
|
|
||||||
CHOICES = (
|
CHOICES = (
|
||||||
(STATUS_ACTIVE, 'Active'),
|
(STATUS_ACTIVE, 'Active'),
|
||||||
(STATUS_RESERVED, 'Reserved'),
|
(STATUS_RESERVED, 'Reserved'),
|
||||||
(STATUS_DEPRECATED, 'Deprecated'),
|
(STATUS_DEPRECATED, 'Deprecated'),
|
||||||
(STATUS_DHCP, 'DHCP'),
|
(STATUS_DHCP, 'DHCP'),
|
||||||
|
(STATUS_SLAAC, 'SLAAC'),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ from django.core.validators import URLValidator
|
|||||||
# Environment setup
|
# Environment setup
|
||||||
#
|
#
|
||||||
|
|
||||||
VERSION = '2.9.0'
|
VERSION = '2.9.1'
|
||||||
|
|
||||||
# Hostname
|
# Hostname
|
||||||
HOSTNAME = platform.node()
|
HOSTNAME = platform.node()
|
||||||
@ -142,6 +142,13 @@ if type(REMOTE_AUTH_DEFAULT_PERMISSIONS) is not dict:
|
|||||||
)
|
)
|
||||||
except TypeError:
|
except TypeError:
|
||||||
raise ImproperlyConfigured("REMOTE_AUTH_DEFAULT_PERMISSIONS must be a dictionary.")
|
raise ImproperlyConfigured("REMOTE_AUTH_DEFAULT_PERMISSIONS must be a dictionary.")
|
||||||
|
# Backward compatibility for REMOTE_AUTH_BACKEND
|
||||||
|
if REMOTE_AUTH_BACKEND == 'utilities.auth_backends.RemoteUserBackend':
|
||||||
|
warnings.warn(
|
||||||
|
"RemoteUserBackend has moved! Please update your configuration to:\n"
|
||||||
|
" REMOTE_AUTH_BACKEND='netbox.authentication.RemoteUserBackend'"
|
||||||
|
)
|
||||||
|
REMOTE_AUTH_BACKEND = 'netbox.authentication.RemoteUserBackend'
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -31,7 +31,10 @@
|
|||||||
The complete exception is provided below:
|
The complete exception is provided below:
|
||||||
</p>
|
</p>
|
||||||
<pre><strong>{{ exception }}</strong><br />
|
<pre><strong>{{ exception }}</strong><br />
|
||||||
{{ error }}</pre>
|
{{ error }}
|
||||||
|
|
||||||
|
Python version: {{ python_version }}
|
||||||
|
NetBox version: {{ netbox_version }}</pre>
|
||||||
<p>
|
<p>
|
||||||
If further assistance is required, please post to the <a href="https://groups.google.com/forum/#!forum/netbox-discuss">NetBox mailing list</a>.
|
If further assistance is required, please post to the <a href="https://groups.google.com/forum/#!forum/netbox-discuss">NetBox mailing list</a>.
|
||||||
</p>
|
</p>
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
import logging
|
import logging
|
||||||
|
import platform
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
@ -1421,6 +1423,8 @@ def server_error(request, template_name=ERROR_500_TEMPLATE_NAME):
|
|||||||
type_, error, traceback = sys.exc_info()
|
type_, error, traceback = sys.exc_info()
|
||||||
|
|
||||||
return HttpResponseServerError(template.render({
|
return HttpResponseServerError(template.render({
|
||||||
|
'python_version': platform.python_version(),
|
||||||
|
'netbox_version': settings.VERSION,
|
||||||
'exception': str(type_),
|
'exception': str(type_),
|
||||||
'error': error,
|
'error': error,
|
||||||
}))
|
}))
|
||||||
|
Loading…
Reference in New Issue
Block a user