Merge branch 'develop' into develop-2.5

This commit is contained in:
Jeremy Stretch 2018-08-16 16:31:54 -04:00
commit 29380b1120
10 changed files with 1696 additions and 15 deletions

1645
CHANGELOG.md Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,7 @@
from django import forms from django import forms
from django.contrib import admin from django.contrib import admin
from netbox.admin import admin_site
from utilities.forms import LaxURLField from utilities.forms import LaxURLField
from .models import CustomField, CustomFieldChoice, Graph, ExportTemplate, TopologyMap, Webhook from .models import CustomField, CustomFieldChoice, Graph, ExportTemplate, TopologyMap, Webhook
@ -32,7 +33,7 @@ class WebhookForm(forms.ModelForm):
order_content_types(self.fields['obj_type']) order_content_types(self.fields['obj_type'])
@admin.register(Webhook) @admin.register(Webhook, site=admin_site)
class WebhookAdmin(admin.ModelAdmin): class WebhookAdmin(admin.ModelAdmin):
list_display = [ list_display = [
'name', 'models', 'payload_url', 'http_content_type', 'enabled', 'type_create', 'type_update', 'name', 'models', 'payload_url', 'http_content_type', 'enabled', 'type_create', 'type_update',
@ -65,7 +66,7 @@ class CustomFieldChoiceAdmin(admin.TabularInline):
extra = 5 extra = 5
@admin.register(CustomField) @admin.register(CustomField, site=admin_site)
class CustomFieldAdmin(admin.ModelAdmin): class CustomFieldAdmin(admin.ModelAdmin):
inlines = [CustomFieldChoiceAdmin] inlines = [CustomFieldChoiceAdmin]
list_display = ['name', 'models', 'type', 'required', 'filter_logic', 'default', 'weight', 'description'] list_display = ['name', 'models', 'type', 'required', 'filter_logic', 'default', 'weight', 'description']
@ -79,7 +80,7 @@ class CustomFieldAdmin(admin.ModelAdmin):
# Graphs # Graphs
# #
@admin.register(Graph) @admin.register(Graph, site=admin_site)
class GraphAdmin(admin.ModelAdmin): class GraphAdmin(admin.ModelAdmin):
list_display = ['name', 'type', 'weight', 'source'] list_display = ['name', 'type', 'weight', 'source']
@ -102,7 +103,7 @@ class ExportTemplateForm(forms.ModelForm):
self.fields['content_type'].choices.insert(0, ('', '---------')) self.fields['content_type'].choices.insert(0, ('', '---------'))
@admin.register(ExportTemplate) @admin.register(ExportTemplate, site=admin_site)
class ExportTemplateAdmin(admin.ModelAdmin): class ExportTemplateAdmin(admin.ModelAdmin):
list_display = ['name', 'content_type', 'description', 'mime_type', 'file_extension'] list_display = ['name', 'content_type', 'description', 'mime_type', 'file_extension']
form = ExportTemplateForm form = ExportTemplateForm
@ -112,7 +113,7 @@ class ExportTemplateAdmin(admin.ModelAdmin):
# Topology maps # Topology maps
# #
@admin.register(TopologyMap) @admin.register(TopologyMap, site=admin_site)
class TopologyMapAdmin(admin.ModelAdmin): class TopologyMapAdmin(admin.ModelAdmin):
list_display = ['name', 'slug', 'site'] list_display = ['name', 'slug', 'site']
prepopulated_fields = { prepopulated_fields = {

30
netbox/netbox/admin.py Normal file
View File

@ -0,0 +1,30 @@
from django.conf import settings
from django.contrib.admin import AdminSite
from django.contrib.auth.models import Group, User
from django.contrib.auth.admin import GroupAdmin, UserAdmin
from taggit.admin import TagAdmin
from taggit.models import Tag
class NetBoxAdminSite(AdminSite):
"""
Custom admin site
"""
site_header = 'NetBox Administration'
site_title = 'NetBox'
site_url = '/{}'.format(settings.BASE_PATH)
admin_site = NetBoxAdminSite(name='admin')
# Register external models
admin_site.register(Group, GroupAdmin)
admin_site.register(User, UserAdmin)
admin_site.register(Tag, TagAdmin)
# Modify the template to include an RQ link if django_rq is installed (see RQ_SHOW_ADMIN_LINK)
try:
import django_rq
admin_site.index_template = 'django_rq/index.html'
except ImportError:
pass

View File

@ -271,7 +271,6 @@ RQ_QUEUES = {
'DEFAULT_TIMEOUT': REDIS_DEFAULT_TIMEOUT, 'DEFAULT_TIMEOUT': REDIS_DEFAULT_TIMEOUT,
} }
} }
RQ_SHOW_ADMIN_LINK = True
# drf_yasg settings for Swagger # drf_yasg settings for Swagger
SWAGGER_SETTINGS = { SWAGGER_SETTINGS = {

View File

@ -1,12 +1,12 @@
from django.conf import settings from django.conf import settings
from django.conf.urls import include, url from django.conf.urls import include, url
from django.contrib import admin
from django.views.static import serve from django.views.static import serve
from drf_yasg.views import get_schema_view from drf_yasg.views import get_schema_view
from drf_yasg import openapi from drf_yasg import openapi
from netbox.views import APIRootView, HomeView, SearchView from netbox.views import APIRootView, HomeView, SearchView
from users.views import LoginView, LogoutView from users.views import LoginView, LogoutView
from .admin import admin_site
schema_view = get_schema_view( schema_view = get_schema_view(
openapi.Info( openapi.Info(
@ -58,7 +58,7 @@ _patterns = [
url(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT}), url(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT}),
# Admin # Admin
url(r'^admin/', admin.site.urls), url(r'^admin/', admin_site.urls),
] ]
@ -67,7 +67,6 @@ if settings.WEBHOOKS_ENABLED:
url(r'^admin/webhook-backend-status/', include('django_rq.urls')), url(r'^admin/webhook-backend-status/', include('django_rq.urls')),
] ]
if settings.DEBUG: if settings.DEBUG:
import debug_toolbar import debug_toolbar
_patterns += [ _patterns += [

View File

@ -1,11 +1,12 @@
from django.contrib import admin, messages from django.contrib import admin, messages
from django.shortcuts import redirect, render from django.shortcuts import redirect, render
from netbox.admin import admin_site
from .forms import ActivateUserKeyForm from .forms import ActivateUserKeyForm
from .models import UserKey from .models import UserKey
@admin.register(UserKey) @admin.register(UserKey, site=admin_site)
class UserKeyAdmin(admin.ModelAdmin): class UserKeyAdmin(admin.ModelAdmin):
actions = ['activate_selected'] actions = ['activate_selected']
list_display = ['user', 'is_filled', 'is_active', 'created'] list_display = ['user', 'is_filled', 'is_active', 'created']

View File

@ -54,7 +54,9 @@
<a href="{% url 'dcim:device' pk=device.pk %}">Device</a> <a href="{% url 'dcim:device' pk=device.pk %}">Device</a>
</li> </li>
<li role="presentation"{% if active_tab == 'inventory' %} class="active"{% endif %}> <li role="presentation"{% if active_tab == 'inventory' %} class="active"{% endif %}>
<a href="{% url 'dcim:device_inventory' pk=device.pk %}">Inventory</a> <a href="{% url 'dcim:device_inventory' pk=device.pk %}">
Inventory <span class="badge">{{ device.inventory_items.count }}</span>
</a>
</li> </li>
{% if perms.dcim.napalm_read %} {% if perms.dcim.napalm_read %}
{% if device.status != 1 %} {% if device.status != 1 %}

View File

@ -1,6 +1,7 @@
from django import forms from django import forms
from django.contrib import admin from django.contrib import admin
from netbox.admin import admin_site
from .models import Token from .models import Token
@ -12,7 +13,7 @@ class TokenAdminForm(forms.ModelForm):
model = Token model = Token
@admin.register(Token) @admin.register(Token, site=admin_site)
class TokenAdmin(admin.ModelAdmin): class TokenAdmin(admin.ModelAdmin):
form = TokenAdminForm form = TokenAdminForm
list_display = ['key', 'user', 'created', 'expires', 'write_enabled', 'description'] list_display = ['key', 'user', 'created', 'expires', 'write_enabled', 'description']

View File

@ -90,6 +90,7 @@ class VirtualMachineIPAddressSerializer(WritableNestedSerializer):
class VirtualMachineSerializer(TaggitSerializer, CustomFieldModelSerializer): class VirtualMachineSerializer(TaggitSerializer, CustomFieldModelSerializer):
status = ChoiceField(choices=VM_STATUS_CHOICES, required=False) status = ChoiceField(choices=VM_STATUS_CHOICES, required=False)
site = NestedSiteSerializer(read_only=True)
cluster = NestedClusterSerializer(required=False, allow_null=True) cluster = NestedClusterSerializer(required=False, allow_null=True)
role = NestedDeviceRoleSerializer(required=False, allow_null=True) role = NestedDeviceRoleSerializer(required=False, allow_null=True)
tenant = NestedTenantSerializer(required=False, allow_null=True) tenant = NestedTenantSerializer(required=False, allow_null=True)
@ -102,8 +103,8 @@ class VirtualMachineSerializer(TaggitSerializer, CustomFieldModelSerializer):
class Meta: class Meta:
model = VirtualMachine model = VirtualMachine
fields = [ fields = [
'id', 'name', 'status', 'cluster', 'role', 'tenant', 'platform', 'primary_ip', 'primary_ip4', 'primary_ip6', 'id', 'name', 'status', 'site', 'cluster', 'role', 'tenant', 'platform', 'primary_ip', 'primary_ip4',
'vcpus', 'memory', 'disk', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', 'primary_ip6', 'vcpus', 'memory', 'disk', 'comments', 'tags', 'custom_fields', 'created', 'last_updated',
] ]

View File

@ -43,7 +43,9 @@ class ClusterViewSet(CustomFieldModelViewSet):
# #
class VirtualMachineViewSet(CustomFieldModelViewSet): class VirtualMachineViewSet(CustomFieldModelViewSet):
queryset = VirtualMachine.objects.all() queryset = VirtualMachine.objects.select_related(
'cluster__site', 'role', 'tenant', 'platform', 'primary_ip4', 'primary_ip6'
)
filter_class = filters.VirtualMachineFilter filter_class = filters.VirtualMachineFilter
def get_serializer_class(self): def get_serializer_class(self):