Merge branch 'develop' into develop-2.9

This commit is contained in:
Jeremy Stretch
2020-08-05 09:15:10 -04:00
18 changed files with 104 additions and 32 deletions

View File

@@ -2703,6 +2703,10 @@ class InterfaceFilterForm(DeviceComponentFilterForm):
choices=BOOLEAN_WITH_BLANK_CHOICES
)
)
mac_address = forms.CharField(
required=False,
label='MAC address'
)
tag = TagFilterField(model)

View File

@@ -56,10 +56,49 @@ DEVICE_COUNT = """
<a href="{% url 'dcim:device_list' %}?role={{ record.slug }}">{{ value|default:0 }}</a>
"""
VM_COUNT = """
RACKRESERVATION_ACTIONS = """
<a href="{% url 'dcim:rackreservation_changelog' pk=record.pk %}" class="btn btn-default btn-xs" title="Change log">
<i class="fa fa-history"></i>
</a>
{% if perms.dcim.change_rackreservation %}
<a href="{% url 'dcim:rackreservation_edit' pk=record.pk %}?return_url={{ request.path }}" class="btn btn-xs btn-warning"><i class="glyphicon glyphicon-pencil" aria-hidden="true"></i></a>
{% endif %}
"""
MANUFACTURER_ACTIONS = """
<a href="{% url 'dcim:manufacturer_changelog' slug=record.slug %}" class="btn btn-default btn-xs" title="Change log">
<i class="fa fa-history"></i>
</a>
{% if perms.dcim.change_manufacturer %}
<a href="{% url 'dcim:manufacturer_edit' slug=record.slug %}?return_url={{ request.path }}" class="btn btn-xs btn-warning"><i class="glyphicon glyphicon-pencil" aria-hidden="true"></i></a>
{% endif %}
"""
DEVICEROLE_DEVICE_COUNT = """
<a href="{% url 'dcim:device_list' %}?role={{ record.slug }}">{{ value|default:0 }}</a>
"""
DEVICEROLE_VM_COUNT = """
<a href="{% url 'virtualization:virtualmachine_list' %}?role={{ record.slug }}">{{ value|default:0 }}</a>
"""
DEVICEROLE_ACTIONS = """
<a href="{% url 'dcim:devicerole_changelog' slug=record.slug %}" class="btn btn-default btn-xs" title="Change log">
<i class="fa fa-history"></i>
</a>
{% if perms.dcim.change_devicerole %}
<a href="{% url 'dcim:devicerole_edit' slug=record.slug %}?return_url={{ request.path }}" class="btn btn-xs btn-warning"><i class="glyphicon glyphicon-pencil" aria-hidden="true"></i></a>
{% endif %}
"""
PLATFORM_DEVICE_COUNT = """
<a href="{% url 'dcim:device_list' %}?platform={{ record.slug }}">{{ value|default:0 }}</a>
"""
PLATFORM_VM_COUNT = """
<a href="{% url 'virtualization:virtualmachine_list' %}?platform={{ record.slug }}">{{ value|default:0 }}</a>
"""
STATUS_LABEL = """
<span class="label label-{{ record.get_status_class }}">{{ record.get_status_display }}</span>
"""
@@ -495,11 +534,11 @@ class DeviceBayTemplateTable(ComponentTemplateTable):
class DeviceRoleTable(BaseTable):
pk = ToggleColumn()
device_count = tables.TemplateColumn(
template_code=DEVICE_COUNT,
template_code=DEVICEROLE_DEVICE_COUNT,
verbose_name='Devices'
)
vm_count = tables.TemplateColumn(
template_code=VM_COUNT,
template_code=DEVICEROLE_VM_COUNT,
verbose_name='VMs'
)
color = tables.TemplateColumn(
@@ -522,11 +561,11 @@ class DeviceRoleTable(BaseTable):
class PlatformTable(BaseTable):
pk = ToggleColumn()
device_count = tables.TemplateColumn(
template_code=DEVICE_COUNT,
template_code=PLATFORM_DEVICE_COUNT,
verbose_name='Devices'
)
vm_count = tables.TemplateColumn(
template_code=VM_COUNT,
template_code=PLATFORM_VM_COUNT,
verbose_name='VMs'
)
actions = ButtonsColumn(Platform, pk_field='slug')
@@ -718,8 +757,8 @@ class InterfaceTable(DeviceComponentTable, BaseInterfaceTable):
class Meta(DeviceComponentTable.Meta):
model = Interface
fields = (
'pk', 'device', 'name', 'label', 'enabled', 'type', 'mgmt_only', 'mtu', 'mode', 'description', 'cable',
'ip_addresses', 'untagged_vlan', 'tagged_vlans',
'pk', 'device', 'name', 'label', 'enabled', 'type', 'mgmt_only', 'mtu', 'mode', 'mac_address',
'description', 'cable', 'ip_addresses', 'untagged_vlan', 'tagged_vlans',
)
default_columns = ('pk', 'device', 'name', 'label', 'enabled', 'type', 'description')

View File

@@ -953,8 +953,8 @@ class DeviceRoleBulkDeleteView(BulkDeleteView):
class PlatformListView(ObjectListView):
queryset = Platform.objects.annotate(
device_count=get_subquery(Device, 'device_role'),
vm_count=get_subquery(VirtualMachine, 'role')
device_count=get_subquery(Device, 'platform'),
vm_count=get_subquery(VirtualMachine, 'platform')
)
table = tables.PlatformTable

View File

@@ -219,6 +219,8 @@ class AggregateView(ObjectView):
prefix__net_contained_or_equal=str(aggregate.prefix)
).prefetch_related(
'site', 'role'
).order_by(
'prefix'
).annotate_depth(
limit=0
)

View File

@@ -16,7 +16,7 @@ from django.core.validators import URLValidator
# Environment setup
#
VERSION = '2.9-beta1'
VERSION = '2.9-beta2'
# Hostname
HOSTNAME = platform.node()

View File

@@ -121,7 +121,7 @@ class SecretForm(BootstrapMixin, CustomFieldModelForm):
device=self.cleaned_data['device'],
role=self.cleaned_data['role'],
name=self.cleaned_data['name']
).exists():
).exclude(pk=self.instance.pk).exists():
raise forms.ValidationError(
"Each secret assigned to a device must have a unique combination of role and name"
)

View File

@@ -178,7 +178,7 @@ def get_docs(model):
model._meta.model_name
)
try:
with open(path) as docfile:
with open(path, encoding='utf-8') as docfile:
content = docfile.read()
except FileNotFoundError:
return "Unable to load documentation, file not found: {}".format(path)

View File

@@ -418,13 +418,14 @@ class ObjectEditView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
try:
with transaction.atomic():
object_created = form.instance.pk is None
obj = form.save()
# Check that the new object conforms with any assigned object-level permissions
self.queryset.get(pk=obj.pk)
msg = '{} {}'.format(
'Created' if not form.instance.pk else 'Modified',
'Created' if object_created else 'Modified',
self.queryset.model._meta.verbose_name
)
logger.info(f"{msg} {obj} (PK: {obj.pk})")

View File

@@ -1,4 +1,4 @@
from django.db.models import Count, Prefetch
from django.db.models import Count
from django.shortcuts import get_object_or_404
from rest_framework.decorators import action
from rest_framework.response import Response
@@ -7,7 +7,6 @@ from dcim.models import Device
from extras.api.serializers import RenderedGraphSerializer
from extras.api.views import CustomFieldModelViewSet
from extras.models import Graph
from ipam.models import VLAN
from utilities.api import ModelViewSet
from utilities.utils import get_subquery
from virtualization import filters