Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release v2.0.4 #1230

Merged
merged 20 commits into from
May 25, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
769232f
Post-release version bump
jeremystretch May 18, 2017
c454bfc
Fixed incorrect message
jeremystretch May 18, 2017
fb85867
Converted all object views to class-based views
jeremystretch May 18, 2017
eece8a0
Fixes #1207: Include nested LAG serializer when showing interface con…
jeremystretch May 19, 2017
27c94d9
Fixes #1206: Fix redirection in admin UI after activating secret keys…
jeremystretch May 19, 2017
e6b4d87
Converted all user views to CBVs
jeremystretch May 19, 2017
713c7cd
Cleaned up 500 error template
jeremystretch May 19, 2017
3fa63b7
Converted home view to a CBV
jeremystretch May 19, 2017
77f28e3
Fixes #1214: Add status to list of required fields on child device im…
jeremystretch May 24, 2017
d5587de
Fixes #1213: Corrected table header ordering links
jeremystretch May 24, 2017
6719578
Fixes #1212: Allow assigning new VLANs to global VLAN groups
jeremystretch May 24, 2017
1c489e5
Added a warning to note "untracked migrations" warnings during an upg…
jeremystretch May 24, 2017
68b6c7d
Fixes #1210: Fix TemplateDoesNotExist errors on browsable API views
jeremystretch May 24, 2017
9aad8a7
Fixes #1219: Fix image attachment URLs when BASE_PATH is set
jeremystretch May 24, 2017
f21c6bc
Import unicode_literals
jeremystretch May 24, 2017
138cbf9
Created migrations for transition to Unicode literals
jeremystretch May 24, 2017
ebddc46
PEP8 fix
jeremystretch May 24, 2017
1dd5e2c
Fixes #1229: Fix validation error on forms where API search is used
jeremystretch May 25, 2017
50462ec
Added notes to discourage the prepending of arbitrary tags to issue t…
jeremystretch May 25, 2017
5a18770
Release v2.0.4
jeremystretch May 25, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ sure to include:
* Any error messages generated
* Screenshots (if applicable)

* Please avoid prepending any sort of tag (e.g. "[Bug]") to the issue title.
The issue will be reviewed by a moderator after submission and the appropriate
labels will be applied.

* Keep in mind that we prioritize bugs based on their severity and how
much work is required to resolve them. It may take some time for someone
to address your issue.
Expand Down Expand Up @@ -91,6 +95,10 @@ following:
* Any third-party libraries or other resources which would be
involved

* Please avoid prepending any sort of tag (e.g. "[Feature]") to the issue title.
The issue will be reviewed by a moderator after submission and the appropriate
labels will be applied.

## Submitting Pull Requests

* Be sure to open an issue before starting work on a pull request, and
Expand Down
8 changes: 8 additions & 0 deletions docs/installation/upgrading.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,14 @@ This script:
* Applies any database migrations that were included in the release
* Collects all static files to be served by the HTTP service

!!! note
It's possible that the upgrade script will display a notice warning of unreflected database migrations:

Your models have changes that are not yet reflected in a migration, and so won't be applied.
Run 'manage.py makemigrations' to make new migrations, and then re-run 'manage.py migrate' to apply them.

This may occur due to semantic differences in environment, and can be safely ignored. Never attempt to create new migrations unless you are inentionally modifying the database schema.

# Restart the WSGI Service

Finally, restart the WSGI service to run the new code. If you followed this guide for the initial installation, this is done using `supervisorctl`:
Expand Down
2 changes: 2 additions & 0 deletions netbox/circuits/api/serializers.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import unicode_literals

from rest_framework import serializers

from circuits.models import Provider, Circuit, CircuitTermination, CircuitType
Expand Down
2 changes: 2 additions & 0 deletions netbox/circuits/api/urls.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import unicode_literals

from rest_framework import routers

from . import views
Expand Down
4 changes: 3 additions & 1 deletion netbox/circuits/api/views.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
from django.shortcuts import get_object_or_404
from __future__ import unicode_literals

from rest_framework.decorators import detail_route
from rest_framework.response import Response
from rest_framework.viewsets import ModelViewSet

from django.shortcuts import get_object_or_404

from circuits import filters
from circuits.models import Provider, CircuitTermination, CircuitType, Circuit
from extras.models import Graph, GRAPH_TYPE_PROVIDER
Expand Down
2 changes: 2 additions & 0 deletions netbox/circuits/apps.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import unicode_literals

from django.apps import AppConfig


Expand Down
2 changes: 2 additions & 0 deletions netbox/circuits/filters.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import unicode_literals

import django_filters

from django.db.models import Q
Expand Down
30 changes: 16 additions & 14 deletions netbox/circuits/forms.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import unicode_literals

from django import forms
from django.db.models import Count

Expand Down Expand Up @@ -165,7 +167,9 @@ class CircuitTerminationForm(BootstrapMixin, ChainedFieldsMixin, forms.ModelForm
)
rack = ChainedModelChoiceField(
queryset=Rack.objects.all(),
chains={'site': 'site'},
chains=(
('site', 'site'),
),
required=False,
label='Rack',
widget=APISelect(
Expand All @@ -175,7 +179,10 @@ class CircuitTerminationForm(BootstrapMixin, ChainedFieldsMixin, forms.ModelForm
)
device = ChainedModelChoiceField(
queryset=Device.objects.all(),
chains={'site': 'site', 'rack': 'rack'},
chains=(
('site', 'site'),
('rack', 'rack'),
),
required=False,
label='Device',
widget=APISelect(
Expand All @@ -184,20 +191,13 @@ class CircuitTerminationForm(BootstrapMixin, ChainedFieldsMixin, forms.ModelForm
attrs={'filter-for': 'interface'}
)
)
livesearch = forms.CharField(
required=False,
label='Device',
widget=Livesearch(
query_key='q',
query_url='dcim-api:device-list',
field_to_update='device'
)
)
interface = ChainedModelChoiceField(
queryset=Interface.objects.exclude(form_factor__in=VIRTUAL_IFACE_TYPES).select_related(
'circuit_termination', 'connected_as_a', 'connected_as_b'
),
chains={'device': 'device'},
chains=(
('device', 'device'),
),
required=False,
label='Interface',
widget=APISelect(
Expand All @@ -208,8 +208,10 @@ class CircuitTerminationForm(BootstrapMixin, ChainedFieldsMixin, forms.ModelForm

class Meta:
model = CircuitTermination
fields = ['term_side', 'site', 'rack', 'device', 'livesearch', 'interface', 'port_speed', 'upstream_speed',
'xconnect_id', 'pp_info']
fields = [
'term_side', 'site', 'rack', 'device', 'interface', 'port_speed', 'upstream_speed', 'xconnect_id',
'pp_info',
]
help_texts = {
'port_speed': "Physical circuit speed",
'xconnect_id': "ID of the local cross-connect",
Expand Down
81 changes: 81 additions & 0 deletions netbox/circuits/migrations/0009_unicode_literals.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11 on 2017-05-24 15:34
from __future__ import unicode_literals

import dcim.fields
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('circuits', '0008_circuittermination_interface_protect_on_delete'),
]

operations = [
migrations.AlterField(
model_name='circuit',
name='cid',
field=models.CharField(max_length=50, verbose_name='Circuit ID'),
),
migrations.AlterField(
model_name='circuit',
name='commit_rate',
field=models.PositiveIntegerField(blank=True, null=True, verbose_name='Commit rate (Kbps)'),
),
migrations.AlterField(
model_name='circuit',
name='install_date',
field=models.DateField(blank=True, null=True, verbose_name='Date installed'),
),
migrations.AlterField(
model_name='circuittermination',
name='port_speed',
field=models.PositiveIntegerField(verbose_name='Port speed (Kbps)'),
),
migrations.AlterField(
model_name='circuittermination',
name='pp_info',
field=models.CharField(blank=True, max_length=100, verbose_name='Patch panel/port(s)'),
),
migrations.AlterField(
model_name='circuittermination',
name='term_side',
field=models.CharField(choices=[('A', 'A'), ('Z', 'Z')], max_length=1, verbose_name='Termination'),
),
migrations.AlterField(
model_name='circuittermination',
name='upstream_speed',
field=models.PositiveIntegerField(blank=True, help_text='Upstream speed, if different from port speed', null=True, verbose_name='Upstream speed (Kbps)'),
),
migrations.AlterField(
model_name='circuittermination',
name='xconnect_id',
field=models.CharField(blank=True, max_length=50, verbose_name='Cross-connect ID'),
),
migrations.AlterField(
model_name='provider',
name='account',
field=models.CharField(blank=True, max_length=30, verbose_name='Account number'),
),
migrations.AlterField(
model_name='provider',
name='admin_contact',
field=models.TextField(blank=True, verbose_name='Admin contact'),
),
migrations.AlterField(
model_name='provider',
name='asn',
field=dcim.fields.ASNField(blank=True, null=True, verbose_name='ASN'),
),
migrations.AlterField(
model_name='provider',
name='noc_contact',
field=models.TextField(blank=True, verbose_name='NOC contact'),
),
migrations.AlterField(
model_name='provider',
name='portal_url',
field=models.URLField(blank=True, verbose_name='Portal'),
),
]
6 changes: 4 additions & 2 deletions netbox/circuits/models.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import unicode_literals

from django.contrib.contenttypes.fields import GenericRelation
from django.db import models
from django.urls import reverse
Expand Down Expand Up @@ -110,7 +112,7 @@ class Meta:
unique_together = ['provider', 'cid']

def __str__(self):
return u'{} {}'.format(self.provider, self.cid)
return '{} {}'.format(self.provider, self.cid)

def get_absolute_url(self):
return reverse('circuits:circuit', args=[self.pk])
Expand Down Expand Up @@ -166,7 +168,7 @@ class Meta:
unique_together = ['circuit', 'term_side']

def __str__(self):
return u'{} (Side {})'.format(self.circuit, self.get_term_side_display())
return '{} (Side {})'.format(self.circuit, self.get_term_side_display())

def get_peer_termination(self):
peer_side = 'Z' if self.term_side == 'A' else 'A'
Expand Down
2 changes: 2 additions & 0 deletions netbox/circuits/signals.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import unicode_literals

from django.db.models.signals import post_delete, post_save
from django.dispatch import receiver
from django.utils import timezone
Expand Down
3 changes: 2 additions & 1 deletion netbox/circuits/tables.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from __future__ import unicode_literals

import django_tables2 as tables
from django_tables2.utils import Accessor

from utilities.tables import BaseTable, SearchTable, ToggleColumn

from .models import Circuit, CircuitType, Provider


Expand Down
2 changes: 2 additions & 0 deletions netbox/circuits/tests/test_api.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import unicode_literals

from rest_framework import status
from rest_framework.test import APITestCase

Expand Down
6 changes: 4 additions & 2 deletions netbox/circuits/urls.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import unicode_literals

from django.conf.urls import url

from . import views
Expand All @@ -12,7 +14,7 @@
url(r'^providers/import/$', views.ProviderBulkImportView.as_view(), name='provider_import'),
url(r'^providers/edit/$', views.ProviderBulkEditView.as_view(), name='provider_bulk_edit'),
url(r'^providers/delete/$', views.ProviderBulkDeleteView.as_view(), name='provider_bulk_delete'),
url(r'^providers/(?P<slug>[\w-]+)/$', views.provider, name='provider'),
url(r'^providers/(?P<slug>[\w-]+)/$', views.ProviderView.as_view(), name='provider'),
url(r'^providers/(?P<slug>[\w-]+)/edit/$', views.ProviderEditView.as_view(), name='provider_edit'),
url(r'^providers/(?P<slug>[\w-]+)/delete/$', views.ProviderDeleteView.as_view(), name='provider_delete'),

Expand All @@ -28,7 +30,7 @@
url(r'^circuits/import/$', views.CircuitBulkImportView.as_view(), name='circuit_import'),
url(r'^circuits/edit/$', views.CircuitBulkEditView.as_view(), name='circuit_bulk_edit'),
url(r'^circuits/delete/$', views.CircuitBulkDeleteView.as_view(), name='circuit_bulk_delete'),
url(r'^circuits/(?P<pk>\d+)/$', views.circuit, name='circuit'),
url(r'^circuits/(?P<pk>\d+)/$', views.CircuitView.as_view(), name='circuit'),
url(r'^circuits/(?P<pk>\d+)/edit/$', views.CircuitEditView.as_view(), name='circuit_edit'),
url(r'^circuits/(?P<pk>\d+)/delete/$', views.CircuitDeleteView.as_view(), name='circuit_delete'),
url(r'^circuits/(?P<pk>\d+)/terminations/swap/$', views.circuit_terminations_swap, name='circuit_terminations_swap'),
Expand Down
65 changes: 37 additions & 28 deletions netbox/circuits/views.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
from __future__ import unicode_literals

from django.contrib import messages
from django.contrib.auth.decorators import permission_required
from django.contrib.auth.mixins import PermissionRequiredMixin
from django.db import transaction
from django.db.models import Count
from django.shortcuts import get_object_or_404, redirect, render
from django.urls import reverse
from django.views.generic import View

from extras.models import Graph, GRAPH_TYPE_PROVIDER
from utilities.forms import ConfirmationForm
from utilities.views import (
BulkDeleteView, BulkEditView, BulkImportView, ObjectDeleteView, ObjectEditView, ObjectListView,
)

from . import filters, forms, tables
from .models import Circuit, CircuitTermination, CircuitType, Provider, TERM_SIDE_A, TERM_SIDE_Z

Expand All @@ -28,18 +30,23 @@ class ProviderListView(ObjectListView):
template_name = 'circuits/provider_list.html'


def provider(request, slug):
class ProviderView(View):

provider = get_object_or_404(Provider, slug=slug)
circuits = Circuit.objects.filter(provider=provider).select_related('type', 'tenant')\
.prefetch_related('terminations__site')
show_graphs = Graph.objects.filter(type=GRAPH_TYPE_PROVIDER).exists()
def get(self, request, slug):

return render(request, 'circuits/provider.html', {
'provider': provider,
'circuits': circuits,
'show_graphs': show_graphs,
})
provider = get_object_or_404(Provider, slug=slug)
circuits = Circuit.objects.filter(provider=provider).select_related(
'type', 'tenant'
).prefetch_related(
'terminations__site'
)
show_graphs = Graph.objects.filter(type=GRAPH_TYPE_PROVIDER).exists()

return render(request, 'circuits/provider.html', {
'provider': provider,
'circuits': circuits,
'show_graphs': show_graphs,
})


class ProviderEditView(PermissionRequiredMixin, ObjectEditView):
Expand Down Expand Up @@ -117,25 +124,27 @@ class CircuitListView(ObjectListView):
template_name = 'circuits/circuit_list.html'


def circuit(request, pk):
class CircuitView(View):

circuit = get_object_or_404(Circuit.objects.select_related('provider', 'type', 'tenant__group'), pk=pk)
termination_a = CircuitTermination.objects.select_related(
'site__region', 'interface__device'
).filter(
circuit=circuit, term_side=TERM_SIDE_A
).first()
termination_z = CircuitTermination.objects.select_related(
'site__region', 'interface__device'
).filter(
circuit=circuit, term_side=TERM_SIDE_Z
).first()
def get(self, request, pk):

return render(request, 'circuits/circuit.html', {
'circuit': circuit,
'termination_a': termination_a,
'termination_z': termination_z,
})
circuit = get_object_or_404(Circuit.objects.select_related('provider', 'type', 'tenant__group'), pk=pk)
termination_a = CircuitTermination.objects.select_related(
'site__region', 'interface__device'
).filter(
circuit=circuit, term_side=TERM_SIDE_A
).first()
termination_z = CircuitTermination.objects.select_related(
'site__region', 'interface__device'
).filter(
circuit=circuit, term_side=TERM_SIDE_Z
).first()

return render(request, 'circuits/circuit.html', {
'circuit': circuit,
'termination_a': termination_a,
'termination_z': termination_z,
})


class CircuitEditView(PermissionRequiredMixin, ObjectEditView):
Expand Down
2 changes: 2 additions & 0 deletions netbox/dcim/api/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import unicode_literals

from rest_framework.exceptions import APIException


Expand Down
Loading