Merge branch 'develop' into select2-ui

This commit is contained in:
John Anderson 2019-01-15 10:26:39 -08:00 committed by GitHub
commit d6d8b078b9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 1968 additions and 1950 deletions

View File

@ -17,15 +17,20 @@ about: Report a reproducible bug in the current release of NetBox
--> -->
### Environment ### Environment
* Python version: <!-- Example: 3.5.4 --> * Python version: <!-- Example: 3.5.4 -->
* NetBox version: <!-- Example: 2.3.6 --> * NetBox version: <!-- Example: 2.5.2 -->
<!-- <!--
Describe in detail the steps that someone else can take to reproduce this Describe in detail the exact steps that someone else can take to reproduce
bug using the current stable release of NetBox (or the current beta release this bug using the current stable release of NetBox (or the current beta
where applicable). release where applicable). Begin with the creation of any necessary
database objects and call out every operation being performed explicitly.
If reporting a bug in the REST API, be sure to reconstruct the raw HTTP
request(s) being made: Don't rely on a wrapper like pynetbox.
--> -->
### Steps to Reproduce ### Steps to Reproduce
1.
2.
3.
<!-- What did you expect to happen? --> <!-- What did you expect to happen? -->
### Expected Behavior ### Expected Behavior

File diff suppressed because it is too large Load Diff

View File

@ -2558,52 +2558,55 @@ class Cable(ChangeLoggedModel):
def clean(self): def clean(self):
# Check that termination types are compatible if self.termination_a and self.termination_b:
type_a = self.termination_a_type.model
type_b = self.termination_b_type.model
if type_b not in COMPATIBLE_TERMINATION_TYPES.get(type_a):
raise ValidationError("Incompatible termination types: {} and {}".format(
self.termination_a_type, self.termination_b_type
))
# A termination point cannot be connected to itself type_a = self.termination_a_type.model
if self.termination_a == self.termination_b: type_b = self.termination_b_type.model
raise ValidationError("Cannot connect {} to itself".format(self.termination_a_type))
# A front port cannot be connected to its corresponding rear port # Check that termination types are compatible
if ( if type_b not in COMPATIBLE_TERMINATION_TYPES.get(type_a):
type_a in ['frontport', 'rearport'] and raise ValidationError("Incompatible termination types: {} and {}".format(
type_b in ['frontport', 'rearport'] and self.termination_a_type, self.termination_b_type
( ))
getattr(self.termination_a, 'rear_port', None) == self.termination_b or
getattr(self.termination_b, 'rear_port', None) == self.termination_a
)
):
raise ValidationError("A front port cannot be connected to it corresponding rear port")
# Check for an existing Cable connected to either termination object # A termination point cannot be connected to itself
if self.termination_a.cable not in (None, self): if self.termination_a == self.termination_b:
raise ValidationError("{} already has a cable attached (#{})".format( raise ValidationError("Cannot connect {} to itself".format(self.termination_a_type))
self.termination_a, self.termination_a.cable_id
))
if self.termination_b.cable not in (None, self):
raise ValidationError("{} already has a cable attached (#{})".format(
self.termination_b, self.termination_b.cable_id
))
# Virtual interfaces cannot be connected # A front port cannot be connected to its corresponding rear port
endpoint_a, endpoint_b, _ = self.get_path_endpoints() if (
if ( type_a in ['frontport', 'rearport'] and
( type_b in ['frontport', 'rearport'] and
isinstance(endpoint_a, Interface) and (
endpoint_a.form_factor == IFACE_FF_VIRTUAL getattr(self.termination_a, 'rear_port', None) == self.termination_b or
) or getattr(self.termination_b, 'rear_port', None) == self.termination_a
( )
isinstance(endpoint_b, Interface) and ):
endpoint_b.form_factor == IFACE_FF_VIRTUAL raise ValidationError("A front port cannot be connected to it corresponding rear port")
)
): # Check for an existing Cable connected to either termination object
raise ValidationError("Cannot connect to a virtual interface") if self.termination_a.cable not in (None, self):
raise ValidationError("{} already has a cable attached (#{})".format(
self.termination_a, self.termination_a.cable_id
))
if self.termination_b.cable not in (None, self):
raise ValidationError("{} already has a cable attached (#{})".format(
self.termination_b, self.termination_b.cable_id
))
# Virtual interfaces cannot be connected
endpoint_a, endpoint_b, _ = self.get_path_endpoints()
if (
(
isinstance(endpoint_a, Interface) and
endpoint_a.form_factor == IFACE_FF_VIRTUAL
) or
(
isinstance(endpoint_b, Interface) and
endpoint_b.form_factor == IFACE_FF_VIRTUAL
)
):
raise ValidationError("Cannot connect to a virtual interface")
# Validate length and length_unit # Validate length and length_unit
if self.length is not None and self.length_unit is None: if self.length is not None and self.length_unit is None:

View File

@ -162,7 +162,7 @@ class RegionBulkImportView(PermissionRequiredMixin, BulkImportView):
class RegionBulkDeleteView(PermissionRequiredMixin, BulkDeleteView): class RegionBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
permission_required = 'dcim.delete_region' permission_required = 'dcim.delete_region'
queryset = Region.objects.annotate(site_count=Count('sites')) queryset = Region.objects.all()
filter = filters.RegionFilter filter = filters.RegionFilter
table = tables.RegionTable table = tables.RegionTable
default_return_url = 'dcim:region_list' default_return_url = 'dcim:region_list'

View File

@ -996,6 +996,7 @@ class IPAddressFilterForm(BootstrapMixin, CustomFieldFilterForm):
choices=IPADDRESS_ROLE_CHOICES, choices=IPADDRESS_ROLE_CHOICES,
required=False, required=False,
widget=StaticSelect2Multiple() widget=StaticSelect2Multiple()
include_null=True,
) )

View File

@ -22,7 +22,7 @@ except ImportError:
) )
VERSION = '2.5.3-dev' VERSION = '2.5.4-dev'
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))