Просмотр исходного кода

Merge pull request #5034 from netbox-community/develop

Release v2.9.1 - 2020-08-22
Jeremy Stretch 5 лет назад
Родитель
Сommit
848cfeb353

+ 9 - 2
docs/installation/upgrading.md

@@ -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
-    Beginning with version 2.8, NetBox requires Python 3.6 or later.
+## Update Dependencies to Required Versions
+
+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
 
 

+ 1 - 1
docs/models/dcim/interface.md

@@ -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.)
 
 

+ 1 - 0
docs/models/ipam/ipaddress.md

@@ -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:
 
 

+ 15 - 1
docs/release-notes/version-2.9.md

@@ -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

+ 1 - 0
mkdocs.yml

@@ -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'

+ 4 - 1
netbox/dcim/forms.py

@@ -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)

+ 5 - 11
netbox/dcim/models/device_components.py

@@ -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:
-            raise ValidationError({
-                'lag': "{} interfaces cannot have a parent LAG interface.".format(self.get_type_display())
-            })
+        if self.type == InterfaceTypeChoices.TYPE_VIRTUAL and self.lag is not None:
+            raise ValidationError({'lag': "Virtual interfaces cannot have a parent LAG interface."})
 
 
-        # Only a LAG can have LAG members
-        if self.type != InterfaceTypeChoices.TYPE_LAG and self.member_interfaces.exists():
-            raise ValidationError({
-                'type': "Cannot change interface type; it has LAG members ({}).".format(
-                    ", ".join([iface.name for iface in self.member_interfaces.all()])
-                )
-            })
+        # A LAG interface cannot be its own parent
+        if self.pk and self.lag_id == self.pk:
+            raise ValidationError({'lag': "A LAG interface cannot be its own parent."})
 
 
         # 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]:

+ 2 - 0
netbox/ipam/choices.py

@@ -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'),
     )
     )
 
 
 
 

+ 8 - 1
netbox/netbox/settings.py

@@ -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'
 
 
 
 
 #
 #

+ 4 - 1
netbox/templates/500.html

@@ -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>

+ 4 - 0
netbox/utilities/views.py

@@ -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,
     }))
     }))