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 v1.8.2 #814

Merged
merged 35 commits into from
Jan 18, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
99cd78c
Post-release version bump
jeremystretch Jan 4, 2017
23c6451
Fixes #776: Prevent circuits from appearing twice while searching
jeremystretch Jan 4, 2017
381eb66
Added alternative installations section
jeremystretch Jan 4, 2017
09fe328
Standardized template names
jeremystretch Jan 5, 2017
dbf9840
Corrected permissions for device component form rendering
jeremystretch Jan 5, 2017
ac72e90
Fixes #778: Refactored order_interfaces() to fix InterfaceTemplate or…
jeremystretch Jan 5, 2017
73ae87a
Updated circuits documentation
jeremystretch Jan 5, 2017
1486a89
Update CONTRIBUTING.md
zevlag Jan 5, 2017
2ef1e62
Merge pull request #781 from zevlag/patch-1
jeremystretch Jan 6, 2017
c9e7c12
Closes #284: Added interface_ordering field to DeviceType
jeremystretch Jan 6, 2017
424c2a5
Table rendering optimizations
jeremystretch Jan 6, 2017
97c0f23
Add description field to TenantSerializer
rburkholder Jan 13, 2017
466c505
Corrected PEP8 errors
jeremystretch Jan 13, 2017
98e2145
Merge pull request #796 from rburkholder/rburkholder-patch-TenantSeri…
jeremystretch Jan 13, 2017
cfaf8b9
added duplicates() method to IPAddress and Prefix model managers.
Jan 16, 2017
eedec19
Added model tests for duplicate prefix and IPs.
Jan 16, 2017
485a21f
cleaned up IPAddress clean() to be more like Prefix's
Jan 16, 2017
edf29e7
moved duplicates() method to model instead of manager.
Jan 17, 2017
398faf5
Merge pull request #804 from digitalocean/prefix-unique
jeremystretch Jan 17, 2017
ab706d2
Follow-up to #804
jeremystretch Jan 17, 2017
0ad2670
Closes #805: Linkify site column in device table
jeremystretch Jan 17, 2017
03859d7
Closes #803: Clarify that no child objects are deleted when deleting …
jeremystretch Jan 17, 2017
07997b2
Fixes #785: Trigger validation error when importing a prefix assigned…
jeremystretch Jan 17, 2017
b3f20aa
Closes #783: Add a description field to the Circuit model
jeremystretch Jan 17, 2017
c264281
Add an empty label (global) to IPAddressBulkAddForm VRF field
jeremystretch Jan 17, 2017
7f3b358
Fixes #807: Redirect user back to form when adding IP addresses in bu…
jeremystretch Jan 17, 2017
f8a4f1b
Closes #797: Add description column to VLANs table
jeremystretch Jan 17, 2017
769537f
Fixes #810: Suppress unique IP validation on invalid IP addresses and…
jeremystretch Jan 18, 2017
fc7f88d
Regression fix: order_naturally() must come first in the queryset def…
jeremystretch Jan 18, 2017
9ff59ab
Closes #760: Redirect user back to device view after deleting an assi…
jeremystretch Jan 18, 2017
3eb969d
Standardized the use of return_url for ObjectDeleteView
jeremystretch Jan 18, 2017
cdccc3a
Ditched get_parent_url() model method in favor of overrideable get_re…
jeremystretch Jan 18, 2017
28a9307
Deprecated use_obj_view in favor of get_return_url()
jeremystretch Jan 18, 2017
74e48fc
PEP8 fixes
jeremystretch Jan 18, 2017
6121f97
Release v1.8.2
jeremystretch Jan 18, 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
7 changes: 3 additions & 4 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,9 @@ If you encounter any issues installing or using NetBox, try one of the following
Join the #netbox channel on [Freenode IRC](https://freenode.net/). You can connect to Freenode at irc.freenode.net using
an IRC client, or you can use their [webchat client](https://webchat.freenode.net/).

### Reddit
### Mailing List

We have established [/r/netbox](https://www.reddit.com/r/netbox) on Reddit for NetBox issues and general discussion.
Reddit registration is free and does not require providing an email address (although it is encouraged).
We have established a Google Groups Mailing List for issues and general discussion. You can find us [here]( https://groups.google.com/forum/#!forum/netbox-discuss).

## Reporting Bugs

Expand All @@ -24,7 +23,7 @@ click "add a reaction" in the top right corner of the issue and add a thumbs up
comment describing how it's affecting your installation. This will allow us to prioritize bugs based on how many users
are affected.

* If you haven't found an existing issue that describes your suspected bug, please inquire about it on IRC or Reddit.
* If you haven't found an existing issue that describes your suspected bug, please inquire about it on IRC or Google Groups.
**Do not** file an issue until you have received confirmation that it is in fact a bug. Invalid issues are very
distracting and slow the pace at which NetBox is developed.

Expand Down
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ NetBox is an IP address management (IPAM) and data center infrastructure managem

NetBox runs as a web application atop the [Django](https://www.djangoproject.com/) Python framework with a [PostgreSQL](http://www.postgresql.org/) database. For a complete list of requirements, see `requirements.txt`. The code is available [on GitHub](https://github.com/digitalocean/netbox).

The complete documentation for Netbox can be found at [Read the Docs](http://netbox.readthedocs.io/en/latest/).
The complete documentation for NetBox can be found at [Read the Docs](http://netbox.readthedocs.io/en/stable/).

Questions? Comments? Please subscribe to [the netbox-discuss mailing list](https://groups.google.com/forum/#!forum/netbox-discuss), or join us on IRC in **#netbox** on **irc.freenode.net**!

Expand All @@ -25,6 +25,9 @@ Questions? Comments? Please subscribe to [the netbox-discuss mailing list](https

# Installation

Please see [the documentation](http://netbox.readthedocs.io/en/latest/) for instructions on installing NetBox.
Please see [the documentation](http://netbox.readthedocs.io/en/stable/) for instructions on installing NetBox. To upgrade NetBox, please download the [latest release](https://github.com/digitalocean/netbox/releases) and run `upgrade.sh`.

To upgrade NetBox, please download the [latest release](https://github.com/digitalocean/netbox/releases) and run `upgrade.sh`.
## Alternative Installations

* [Docker container](http://netbox.readthedocs.io/en/stable/installation/docker/)
* [Heroku deployment](https://heroku.com/deploy?template=https://github.com/BILDQUADRAT/netbox/tree/heroku) (via [@mraerino](https://github.com/BILDQUADRAT/netbox/tree/heroku))
25 changes: 13 additions & 12 deletions docs/data-model/circuits.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,30 @@ The circuits component of NetBox deals with the management of long-haul Internet

A provider is any entity which provides some form of connectivity. This obviously includes carriers which offer Internet and private transit service. However, it might also include Internet exchange (IX) points and even organizations with whom you peer directly.

Each provider may be assigned an autonomous system number (ASN) for reference. Each provider can also be assigned account and contact information, as well as miscellaneous comments.
Each provider may be assigned an autonomous system number (ASN), an account number, and contact information.

---

# Circuits

A circuit represents a single physical data link connecting two endpoints. Each circuit belongs to a provider and must be assigned circuit ID which is unique to that provider. Each circuit must also be assigned to a site, and may optionally be connected to a specific interface on a specific device within that site.

NetBox also tracks miscellaneous circuit attributes (most of which are optional), including:

* Date of installation
* Port speed
* Commit rate
* Cross-connect ID
* Patch panel information
A circuit represents a single physical data link connecting two endpoints. Each circuit belongs to a provider and must be assigned a circuit ID which is unique to that provider.

### Circuit Types

Circuits can be classified by type. For example:
Circuits are classified by type. For example:

* Internet transit
* Out-of-band connectivity
* Peering
* Private backhaul

Each circuit must be assigned exactly one circuit type.
Circuit types are fully customizable.

### Circuit Terminations

A circuit may have one or two terminations, annotated as the "A" and "Z" sides of the circuit. A single-termination circuit can be used when you don't know (or care) about the far end of a circuit (for example, an Internet access circuit which connects to a transit provider). A dual-termination circuit is useful for tracking circuits which connect two sites.

Each circuit termination can be tied to a site, or to a specific device and interface within that site. Each termination can be assigned a separate downstream and upstream speed independent from one another. Fields are also available to track cross-connect and patch panel details.

!!! note
A circuit represents a physical link, and cannot have more than two endpoints. When modeling a multi-point topology, each leg of the topology must be defined as a discrete circuit.
3 changes: 2 additions & 1 deletion netbox/circuits/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ class CircuitSerializer(CustomFieldSerializer, serializers.ModelSerializer):

class Meta:
model = Circuit
fields = ['id', 'cid', 'provider', 'type', 'tenant', 'install_date', 'commit_rate', 'comments', 'terminations', 'custom_fields']
fields = ['id', 'cid', 'provider', 'type', 'tenant', 'install_date', 'commit_rate', 'description', 'comments',
'terminations', 'custom_fields']


class CircuitNestedSerializer(CircuitSerializer):
Expand Down
3 changes: 2 additions & 1 deletion netbox/circuits/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,5 +98,6 @@ def search(self, queryset, value):
Q(cid__icontains=value) |
Q(terminations__xconnect_id__icontains=value) |
Q(terminations__pp_info__icontains=value) |
Q(description__icontains=value) |
Q(comments__icontains=value)
)
).distinct()
7 changes: 4 additions & 3 deletions netbox/circuits/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ class CircuitForm(BootstrapMixin, CustomFieldForm):

class Meta:
model = Circuit
fields = ['cid', 'type', 'provider', 'tenant', 'install_date', 'commit_rate', 'comments']
fields = ['cid', 'type', 'provider', 'tenant', 'install_date', 'commit_rate', 'description', 'comments']
help_texts = {
'cid': "Unique circuit ID",
'install_date': "Format: YYYY-MM-DD",
Expand All @@ -104,7 +104,7 @@ class CircuitFromCSVForm(forms.ModelForm):

class Meta:
model = Circuit
fields = ['cid', 'provider', 'type', 'tenant', 'install_date', 'commit_rate']
fields = ['cid', 'provider', 'type', 'tenant', 'install_date', 'commit_rate', 'description']


class CircuitImportForm(BootstrapMixin, BulkImportForm):
Expand All @@ -117,10 +117,11 @@ class CircuitBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
provider = forms.ModelChoiceField(queryset=Provider.objects.all(), required=False)
tenant = forms.ModelChoiceField(queryset=Tenant.objects.all(), required=False)
commit_rate = forms.IntegerField(required=False, label='Commit rate (Kbps)')
description = forms.CharField(max_length=100, required=False)
comments = CommentField(widget=SmallTextarea)

class Meta:
nullable_fields = ['tenant', 'commit_rate', 'comments']
nullable_fields = ['tenant', 'commit_rate', 'description', 'comments']


class CircuitFilterForm(BootstrapMixin, CustomFieldFilterForm):
Expand Down
20 changes: 20 additions & 0 deletions netbox/circuits/migrations/0007_circuit_add_description.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.4 on 2017-01-17 20:08
from __future__ import unicode_literals

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('circuits', '0006_terminations'),
]

operations = [
migrations.AddField(
model_name='circuit',
name='description',
field=models.CharField(blank=True, max_length=100),
),
]
5 changes: 2 additions & 3 deletions netbox/circuits/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ class Circuit(CreatedUpdatedModel, CustomFieldModel):
tenant = models.ForeignKey(Tenant, related_name='circuits', blank=True, null=True, on_delete=models.PROTECT)
install_date = models.DateField(blank=True, null=True, verbose_name='Date installed')
commit_rate = models.PositiveIntegerField(blank=True, null=True, verbose_name='Commit rate (Kbps)')
description = models.CharField(max_length=100, blank=True)
comments = models.TextField(blank=True)
custom_field_values = GenericRelation(CustomFieldValue, content_type_field='obj_type', object_id_field='obj_id')

Expand All @@ -118,6 +119,7 @@ def to_csv(self):
self.tenant.name if self.tenant else None,
self.install_date.isoformat() if self.install_date else None,
self.commit_rate,
self.description,
])

def _get_termination(self, side):
Expand Down Expand Up @@ -157,9 +159,6 @@ class Meta:
def __unicode__(self):
return u'{} (Side {})'.format(self.circuit, self.get_term_side_display())

def get_parent_url(self):
return self.circuit.get_absolute_url()

def get_peer_termination(self):
peer_side = 'Z' if self.term_side == 'A' else 'A'
try:
Expand Down
5 changes: 2 additions & 3 deletions netbox/circuits/tables.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,8 @@ class CircuitTable(BaseTable):
args=[Accessor('termination_a.site.slug')])
z_side = tables.LinkColumn('dcim:site', accessor=Accessor('termination_z.site'), orderable=False,
args=[Accessor('termination_z.site.slug')])
commit_rate = tables.Column(accessor=Accessor('commit_rate_human'), order_by=Accessor('commit_rate'),
verbose_name='Commit Rate')
description = tables.Column(verbose_name='Description')

class Meta(BaseTable.Meta):
model = Circuit
fields = ('pk', 'cid', 'type', 'provider', 'tenant', 'a_side', 'z_side', 'commit_rate')
fields = ('pk', 'cid', 'type', 'provider', 'tenant', 'a_side', 'z_side', 'description')
16 changes: 10 additions & 6 deletions netbox/circuits/views.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from django.contrib import messages
from django.contrib.auth.decorators import permission_required
from django.contrib.auth.mixins import PermissionRequiredMixin
from django.core.urlresolvers import reverse
from django.db import transaction
from django.db.models import Count
from django.shortcuts import get_object_or_404, redirect, render
Expand Down Expand Up @@ -52,7 +53,7 @@ class ProviderEditView(PermissionRequiredMixin, ObjectEditView):
class ProviderDeleteView(PermissionRequiredMixin, ObjectDeleteView):
permission_required = 'circuits.delete_provider'
model = Provider
redirect_url = 'circuits:provider_list'
default_return_url = 'circuits:provider_list'


class ProviderBulkImportView(PermissionRequiredMixin, BulkImportView):
Expand Down Expand Up @@ -92,8 +93,9 @@ class CircuitTypeEditView(PermissionRequiredMixin, ObjectEditView):
permission_required = 'circuits.change_circuittype'
model = CircuitType
form_class = forms.CircuitTypeForm
obj_list_url = 'circuits:circuittype_list'
use_obj_view = False

def get_return_url(self, obj):
return reverse('circuits:circuittype_list')


class CircuitTypeBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
Expand Down Expand Up @@ -140,7 +142,7 @@ class CircuitEditView(PermissionRequiredMixin, ObjectEditView):
class CircuitDeleteView(PermissionRequiredMixin, ObjectDeleteView):
permission_required = 'circuits.delete_circuit'
model = Circuit
redirect_url = 'circuits:circuit_list'
default_return_url = 'circuits:circuit_list'


class CircuitBulkImportView(PermissionRequiredMixin, BulkImportView):
Expand Down Expand Up @@ -223,10 +225,12 @@ class CircuitTerminationEditView(PermissionRequiredMixin, ObjectEditView):

def alter_obj(self, obj, args, kwargs):
if 'circuit' in kwargs:
circuit = get_object_or_404(Circuit, pk=kwargs['circuit'])
obj.circuit = circuit
obj.circuit = get_object_or_404(Circuit, pk=kwargs['circuit'])
return obj

def get_return_url(self, obj):
return obj.circuit.get_absolute_url()


class CircuitTerminationDeleteView(PermissionRequiredMixin, ObjectDeleteView):
permission_required = 'circuits.delete_circuittermination'
Expand Down
9 changes: 5 additions & 4 deletions netbox/dcim/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,8 @@ class DeviceTypeSerializer(CustomFieldSerializer, serializers.ModelSerializer):
class Meta:
model = DeviceType
fields = ['id', 'manufacturer', 'model', 'slug', 'part_number', 'u_height', 'is_full_depth',
'is_console_server', 'is_pdu', 'is_network_device', 'subdevice_role', 'comments', 'custom_fields']
'interface_ordering', 'is_console_server', 'is_pdu', 'is_network_device', 'subdevice_role',
'comments', 'custom_fields']

def get_subdevice_role(self, obj):
return {
Expand Down Expand Up @@ -198,9 +199,9 @@ class DeviceTypeDetailSerializer(DeviceTypeSerializer):

class Meta(DeviceTypeSerializer.Meta):
fields = ['id', 'manufacturer', 'model', 'slug', 'part_number', 'u_height', 'is_full_depth',
'is_console_server', 'is_pdu', 'is_network_device', 'subdevice_role', 'comments', 'custom_fields',
'console_port_templates', 'cs_port_templates', 'power_port_templates', 'power_outlet_templates',
'interface_templates']
'interface_ordering', 'is_console_server', 'is_pdu', 'is_network_device', 'subdevice_role',
'comments', 'custom_fields', 'console_port_templates', 'cs_port_templates', 'power_port_templates',
'power_outlet_templates', 'interface_templates']


#
Expand Down
12 changes: 8 additions & 4 deletions netbox/dcim/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
from .models import (
DeviceBay, DeviceBayTemplate, CONNECTION_STATUS_CHOICES, CONNECTION_STATUS_PLANNED, CONNECTION_STATUS_CONNECTED,
ConsolePort, ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, Device, DeviceRole, DeviceType,
Interface, IFACE_FF_CHOICES, IFACE_FF_VIRTUAL, InterfaceConnection, InterfaceTemplate, Manufacturer, Module,
Platform, PowerOutlet, PowerOutletTemplate, PowerPort, PowerPortTemplate, RACK_TYPE_CHOICES, RACK_WIDTH_CHOICES,
Rack, RackGroup, RackRole, Site, STATUS_CHOICES, SUBDEVICE_ROLE_CHILD
Interface, IFACE_FF_CHOICES, IFACE_FF_VIRTUAL, IFACE_ORDERING_CHOICES, InterfaceConnection, InterfaceTemplate,
Manufacturer, Module, Platform, PowerOutlet, PowerOutletTemplate, PowerPort, PowerPortTemplate, RACK_TYPE_CHOICES,
RACK_WIDTH_CHOICES, Rack, RackGroup, RackRole, Site, STATUS_CHOICES, SUBDEVICE_ROLE_CHILD
)


Expand Down Expand Up @@ -263,13 +263,17 @@ class DeviceTypeForm(BootstrapMixin, CustomFieldForm):
class Meta:
model = DeviceType
fields = ['manufacturer', 'model', 'slug', 'part_number', 'u_height', 'is_full_depth', 'is_console_server',
'is_pdu', 'is_network_device', 'subdevice_role', 'comments']
'is_pdu', 'is_network_device', 'subdevice_role', 'interface_ordering', 'comments']
labels = {
'interface_ordering': 'Order interfaces by',
}


class DeviceTypeBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
pk = forms.ModelMultipleChoiceField(queryset=DeviceType.objects.all(), widget=forms.MultipleHiddenInput)
manufacturer = forms.ModelChoiceField(queryset=Manufacturer.objects.all(), required=False)
u_height = forms.IntegerField(min_value=1, required=False)
interface_ordering = forms.ChoiceField(choices=add_blank_choice(IFACE_ORDERING_CHOICES), required=False)

class Meta:
nullable_fields = []
Expand Down
20 changes: 20 additions & 0 deletions netbox/dcim/migrations/0025_devicetype_add_interface_ordering.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.4 on 2017-01-06 16:56
from __future__ import unicode_literals

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('dcim', '0024_site_add_contact_fields'),
]

operations = [
migrations.AddField(
model_name='devicetype',
name='interface_ordering',
field=models.PositiveSmallIntegerField(choices=[[1, b'Slot/position'], [2, b'Name (alphabetically)']], default=1),
),
]
Loading