Merge branch 'develop' into feature

This commit is contained in:
jeremystretch 2021-04-13 16:41:46 -04:00
commit e3f5062583
7 changed files with 44 additions and 8 deletions

View File

@ -1,4 +1,5 @@
name: 'Close stale issues and PRs' # close-stale-issues (https://github.com/marketplace/actions/close-stale-issues)
name: 'Close stale issues/PRs'
on: on:
schedule: schedule:
- cron: '0 4 * * *' - cron: '0 4 * * *'
@ -9,7 +10,6 @@ jobs:
steps: steps:
- uses: actions/stale@v3 - uses: actions/stale@v3
with: with:
debug-only: true
close-issue-message: > close-issue-message: >
This issue has been automatically closed due to lack of activity. In an This issue has been automatically closed due to lack of activity. In an
effort to reduce noise, please do not comment any further. Note that the effort to reduce noise, please do not comment any further. Note that the
@ -19,7 +19,7 @@ jobs:
This PR has been automatically closed due to lack of activity. This PR has been automatically closed due to lack of activity.
days-before-stale: 45 days-before-stale: 45
days-before-close: 15 days-before-close: 15
exempt-issue-labels: "status: accepted,status: blocked,status: needs milestone" exempt-issue-labels: 'status: accepted,status: blocked,status: needs milestone'
remove-stale-when-updated: false remove-stale-when-updated: false
stale-issue-label: 'pending closure' stale-issue-label: 'pending closure'
stale-issue-message: > stale-issue-message: >
@ -27,7 +27,7 @@ jobs:
recent activity. It will be closed if no further activity occurs. NetBox recent activity. It will be closed if no further activity occurs. NetBox
is governed by a small group of core maintainers which means not all opened is governed by a small group of core maintainers which means not all opened
issues may receive direct feedback. Please see our [contributing guide](https://github.com/netbox-community/netbox/blob/develop/CONTRIBUTING.md). issues may receive direct feedback. Please see our [contributing guide](https://github.com/netbox-community/netbox/blob/develop/CONTRIBUTING.md).
stale-pr-label: "pending closure" stale-pr-label: 'pending closure'
stale-pr-message: > stale-pr-message: >
This PR has been automatically marked as stale because it has not had This PR has been automatically marked as stale because it has not had
recent activity. It will be closed automatically if no further action is recent activity. It will be closed automatically if no further action is

View File

@ -1,5 +1,16 @@
# NetBox v2.10 # NetBox v2.10
## v2.10.10 (FUTURE)
### Bug Fixes
* [#5419](https://github.com/netbox-community/netbox/issues/5419) - Update parent device/VM when deleting a primary IP
* [#6056](https://github.com/netbox-community/netbox/issues/6056) - Optimize change log cleanup
* [#6144](https://github.com/netbox-community/netbox/issues/6144) - Fix MAC address field display in VM interfaces search form
* [#6152](https://github.com/netbox-community/netbox/issues/6152) - Fix custom field filtering for cables, virtual chassis
---
## v2.10.9 (2021-04-12) ## v2.10.9 (2021-04-12)
### Enhancements ### Enhancements

View File

@ -1093,7 +1093,7 @@ class InventoryItemFilterSet(BaseFilterSet, DeviceComponentFilterSet):
return queryset.filter(qs_filter) return queryset.filter(qs_filter)
class VirtualChassisFilterSet(BaseFilterSet): class VirtualChassisFilterSet(BaseFilterSet, CustomFieldModelFilterSet):
q = django_filters.CharFilter( q = django_filters.CharFilter(
method='search', method='search',
label='Search', label='Search',
@ -1173,7 +1173,7 @@ class VirtualChassisFilterSet(BaseFilterSet):
return queryset.filter(qs_filter).distinct() return queryset.filter(qs_filter).distinct()
class CableFilterSet(BaseFilterSet): class CableFilterSet(BaseFilterSet, CustomFieldModelFilterSet):
q = django_filters.CharFilter( q = django_filters.CharFilter(
method='search', method='search',
label='Search', label='Search',

View File

@ -4,6 +4,7 @@ from datetime import timedelta
from cacheops.signals import cache_invalidated, cache_read from cacheops.signals import cache_invalidated, cache_read
from django.conf import settings from django.conf import settings
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.db import DEFAULT_DB_ALIAS
from django.db.models.signals import m2m_changed, pre_delete from django.db.models.signals import m2m_changed, pre_delete
from django.utils import timezone from django.utils import timezone
from django_prometheus.models import model_deletes, model_inserts, model_updates from django_prometheus.models import model_deletes, model_inserts, model_updates
@ -64,7 +65,7 @@ def _handle_changed_object(request, sender, instance, **kwargs):
# Housekeeping: 0.1% chance of clearing out expired ObjectChanges # Housekeeping: 0.1% chance of clearing out expired ObjectChanges
if settings.CHANGELOG_RETENTION and random.randint(1, 1000) == 1: if settings.CHANGELOG_RETENTION and random.randint(1, 1000) == 1:
cutoff = timezone.now() - timedelta(days=settings.CHANGELOG_RETENTION) cutoff = timezone.now() - timedelta(days=settings.CHANGELOG_RETENTION)
ObjectChange.objects.filter(time__lt=cutoff).delete() ObjectChange.objects.filter(time__lt=cutoff)._raw_delete(using=DEFAULT_DB_ALIAS)
def _handle_deleted_object(request, sender, instance, **kwargs): def _handle_deleted_object(request, sender, instance, **kwargs):

View File

@ -4,3 +4,6 @@ from django.apps import AppConfig
class IPAMConfig(AppConfig): class IPAMConfig(AppConfig):
name = "ipam" name = "ipam"
verbose_name = "IPAM" verbose_name = "IPAM"
def ready(self):
import ipam.signals

21
netbox/ipam/signals.py Normal file
View File

@ -0,0 +1,21 @@
from django.db.models.signals import pre_delete
from django.dispatch import receiver
from dcim.models import Device
from virtualization.models import VirtualMachine
from .models import IPAddress
@receiver(pre_delete, sender=IPAddress)
def clear_primary_ip(instance, **kwargs):
"""
When an IPAddress is deleted, trigger save() on any Devices/VirtualMachines for which it
was a primary IP.
"""
field_name = f'primary_ip{instance.family}'
device = Device.objects.filter(**{field_name: instance}).first()
if device:
device.save()
virtualmachine = VirtualMachine.objects.filter(**{field_name: instance}).first()
if virtualmachine:
virtualmachine.save()

View File

@ -806,7 +806,7 @@ class VMInterfaceBulkRenameForm(BulkRenameForm):
) )
class VMInterfaceFilterForm(forms.Form): class VMInterfaceFilterForm(BootstrapMixin, forms.Form):
model = VMInterface model = VMInterface
cluster_id = DynamicModelMultipleChoiceField( cluster_id = DynamicModelMultipleChoiceField(
queryset=Cluster.objects.all(), queryset=Cluster.objects.all(),