Skip to content

Commit

Permalink
Merge pull request #7815 from netbox-community/develop
Browse files Browse the repository at this point in the history
Release v3.0.10
  • Loading branch information
jeremystretch authored Nov 12, 2021
2 parents f5356b8 + 49e7784 commit b29a551
Show file tree
Hide file tree
Showing 35 changed files with 158 additions and 81 deletions.
7 changes: 2 additions & 5 deletions .github/ISSUE_TEMPLATE/bug_report.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,8 @@ body:
- type: input
attributes:
label: NetBox version
description: >
What version of NetBox are you currently running? (If you don't have access to the most
recent NetBox release, consider testing on our [demo instance](https://demo.netbox.dev/)
before opening a bug report to see if your issue has already been addressed.)
placeholder: v3.0.9
description: What version of NetBox are you currently running?
placeholder: v3.0.10
validations:
required: true
- type: dropdown
Expand Down
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/feature_request.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ body:
attributes:
label: NetBox version
description: What version of NetBox are you currently running?
placeholder: v3.0.9
placeholder: v3.0.10
validations:
required: true
- type: dropdown
Expand Down
12 changes: 4 additions & 8 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,10 @@ free to add a comment with any additional justification for the feature.
(However, note that comments with no substance other than a "+1" will be
deleted. Please use GitHub's reactions feature to indicate your support.)

* Due to a large backlog of feature requests, we are not currently accepting
any proposals which substantially extend NetBox's functionality beyond its
current feature set. This includes the introduction of any new views or models
which have not already been proposed in an existing feature request.

* Before filing a new feature request, consider raising your idea on the
mailing list first. Feedback you receive there will help validate and shape the
proposed feature before filing a formal issue.
* Before filing a new feature request, consider raising your idea in a
[GitHub discussion](https://github.com/netbox-community/netbox/discussions)
first. Feedback you receive there will help validate and shape the proposed
feature before filing a formal issue.

* Good feature requests are very narrowly defined. Be sure to thoroughly
describe the functionality and data model(s) being proposed. The more effort
Expand Down
10 changes: 10 additions & 0 deletions docs/core-functionality/devices.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,13 @@ Device components represent discrete objects within a device which are used to t
---

{!models/dcim/cable.md!}

In the example below, three individual cables comprise a path between devices A and D:

![Cable path](../media/models/dcim_cable_trace.png)

Traced from Interface 1 on Device A, NetBox will show the following path:

* Cable 1: Interface 1 to Front Port 1
* Cable 2: Rear Port 1 to Rear Port 2
* Cable 3: Front Port 2 to Interface 2
3 changes: 0 additions & 3 deletions docs/installation/1-postgresql.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,6 @@ This section entails the installation and configuration of a local PostgreSQL da
sudo postgresql-setup --initdb
```

!!! info
PostgreSQL 9.6 and later are available natively on CentOS 8.2. If using an earlier CentOS release, you may need to [install it from an RPM](https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/).

CentOS configures ident host-based authentication for PostgreSQL by default. Because NetBox will need to authenticate using a username and password, modify `/var/lib/pgsql/data/pg_hba.conf` to support MD5 authentication by changing `ident` to `md5` for the lines below:

```no-highlight
Expand Down
7 changes: 6 additions & 1 deletion docs/installation/3-netbox.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,13 @@ Begin by installing all system packages required by NetBox and its dependencies.

=== "CentOS"

!!! warning
CentOS 8 does not provide Python 3.7 or later via its native package manager. You will need to install it via some other means. [Here is an example](https://tecadmin.net/install-python-3-7-on-centos-8/) of installing Python 3.7 from source.

Once you have Python 3.7 or later installed, install the remaining system packages:

```no-highlight
sudo yum install -y gcc python36 python36-devel python3-pip libxml2-devel libxslt-devel libffi-devel libpq-devel openssl-devel redhat-rpm-config
sudo yum install -y gcc libxml2-devel libxslt-devel libffi-devel libpq-devel openssl-devel redhat-rpm-config
```

Before continuing with either platform, update pip (Python's package management tool) to its latest release:
Expand Down
2 changes: 1 addition & 1 deletion docs/installation/index.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Installation

The installation instructions provided here have been tested to work on Ubuntu 20.04 and CentOS 8.2. The particular commands needed to install dependencies on other distributions may vary significantly. Unfortunately, this is outside the control of the NetBox maintainers. Please consult your distribution's documentation for assistance with any errors.
The installation instructions provided here have been tested to work on Ubuntu 20.04 and CentOS 8.3. The particular commands needed to install dependencies on other distributions may vary significantly. Unfortunately, this is outside the control of the NetBox maintainers. Please consult your distribution's documentation for assistance with any errors.

The following sections detail how to set up a new instance of NetBox:

Expand Down
10 changes: 0 additions & 10 deletions docs/models/dcim/cable.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,3 @@ Each cable may be assigned a type, label, length, and color. Each cable is also
## Tracing Cables

A cable may be traced from either of its endpoints by clicking the "trace" button. (A REST API endpoint also provides this functionality.) NetBox will follow the path of connected cables from this termination across the directly connected cable to the far-end termination. If the cable connects to a pass-through port, and the peer port has another cable connected, NetBox will continue following the cable path until it encounters a non-pass-through or unconnected termination point. The entire path will be displayed to the user.

In the example below, three individual cables comprise a path between devices A and D:

![Cable path](../media/models/dcim_cable_trace.png)

Traced from Interface 1 on Device A, NetBox will show the following path:

* Cable 1: Interface 1 to Front Port 1
* Cable 2: Rear Port 1 to Rear Port 2
* Cable 3: Front Port 2 to Interface 2
26 changes: 26 additions & 0 deletions docs/release-notes/version-3.0.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,31 @@
# NetBox v3.0

## v3.0.10 (2021-11-12)

### Enhancements

* [#7740](https://github.com/netbox-community/netbox/issues/7740) - Add mini-DIN 8 console port type
* [#7760](https://github.com/netbox-community/netbox/issues/7760) - Add `vid` filter field to VLANs list
* [#7767](https://github.com/netbox-community/netbox/issues/7767) - Add visual aids to interfaces table for type, enabled status

### Bug Fixes

* [#7564](https://github.com/netbox-community/netbox/issues/7564) - Fix assignment of members to virtual chassis with initial position of zero
* [#7701](https://github.com/netbox-community/netbox/issues/7701) - Fix conflation of assigned IP status & role in interface tables
* [#7741](https://github.com/netbox-community/netbox/issues/7741) - Fix 404 when attaching multiple images in succession
* [#7752](https://github.com/netbox-community/netbox/issues/7752) - Fix minimum version check under Python v3.10
* [#7766](https://github.com/netbox-community/netbox/issues/7766) - Add missing outer dimension columns to rack table
* [#7780](https://github.com/netbox-community/netbox/issues/7780) - Preserve multi-line values during CSV file import
* [#7783](https://github.com/netbox-community/netbox/issues/7783) - Fix indentation of locations under site view
* [#7788](https://github.com/netbox-community/netbox/issues/7788) - Improve XSS mitigation in Markdown renderer
* [#7791](https://github.com/netbox-community/netbox/issues/7791) - Enable sorting device bays table by installed device status
* [#7802](https://github.com/netbox-community/netbox/issues/7802) - Differentiate ID and VID columns in VLANs table
* [#7808](https://github.com/netbox-community/netbox/issues/7808) - Fix reference values for content type under custom field import form
* [#7809](https://github.com/netbox-community/netbox/issues/7809) - Add missing export template support for various models
* [#7814](https://github.com/netbox-community/netbox/issues/7814) - Fix restriction of user & group objects in GraphQL API queries

---

## v3.0.9 (2021-11-03)

### Enhancements
Expand Down
2 changes: 2 additions & 0 deletions netbox/dcim/choices.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ class ConsolePortTypeChoices(ChoiceSet):
TYPE_RJ11 = 'rj-11'
TYPE_RJ12 = 'rj-12'
TYPE_RJ45 = 'rj-45'
TYPE_MINI_DIN_8 = 'mini-din-8'
TYPE_USB_A = 'usb-a'
TYPE_USB_B = 'usb-b'
TYPE_USB_C = 'usb-c'
Expand All @@ -202,6 +203,7 @@ class ConsolePortTypeChoices(ChoiceSet):
(TYPE_RJ11, 'RJ-11'),
(TYPE_RJ12, 'RJ-12'),
(TYPE_RJ45, 'RJ-45'),
(TYPE_MINI_DIN_8, 'Mini-DIN 8'),
)),
('USB', (
(TYPE_USB_A, 'USB Type A'),
Expand Down
10 changes: 8 additions & 2 deletions netbox/dcim/forms/object_create.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,12 +117,18 @@ class Meta:
'name', 'domain', 'region', 'site_group', 'site', 'rack', 'members', 'initial_position', 'tags',
]

def clean(self):
if self.cleaned_data['members'] and self.cleaned_data['initial_position'] is None:
raise forms.ValidationError({
'initial_position': "A position must be specified for the first VC member."
})

def save(self, *args, **kwargs):
instance = super().save(*args, **kwargs)

# Assign VC members
if instance.pk:
initial_position = self.cleaned_data.get('initial_position') or 1
if instance.pk and self.cleaned_data['members']:
initial_position = self.cleaned_data.get('initial_position', 1)
for i, member in enumerate(self.cleaned_data['members'], start=initial_position):
member.virtual_chassis = instance
member.vc_position = i
Expand Down
17 changes: 13 additions & 4 deletions netbox/dcim/tables/devices.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,14 @@ def get_cabletermination_row_class(record):
return ''


def get_interface_row_class(record):
if not record.enabled:
return 'danger'
elif record.is_virtual:
return 'primary'
return get_cabletermination_row_class(record)


def get_interface_state_attribute(record):
"""
Get interface enabled state as string to attach to <tr/> DOM element.
Expand Down Expand Up @@ -501,8 +509,8 @@ class Meta(DeviceComponentTable.Meta):

class DeviceInterfaceTable(InterfaceTable):
name = tables.TemplateColumn(
template_code='<i class="mdi mdi-{% if iface.mgmt_only %}wrench{% elif iface.is_lag %}drag-horizontal-variant'
'{% elif iface.is_virtual %}circle{% elif iface.is_wireless %}wifi{% else %}ethernet'
template_code='<i class="mdi mdi-{% if record.mgmt_only %}wrench{% elif record.is_lag %}reorder-horizontal'
'{% elif record.is_virtual %}circle{% elif record.is_wireless %}wifi{% else %}ethernet'
'{% endif %}"></i> <a href="{{ record.get_absolute_url }}">{{ value }}</a>',
order_by=Accessor('_name'),
attrs={'td': {'class': 'text-nowrap'}}
Expand Down Expand Up @@ -534,7 +542,7 @@ class Meta(DeviceComponentTable.Meta):
'cable', 'connection', 'actions',
)
row_attrs = {
'class': get_cabletermination_row_class,
'class': get_interface_row_class,
'data-name': lambda record: record.name,
'data-enabled': get_interface_state_attribute,
}
Expand Down Expand Up @@ -653,7 +661,8 @@ class DeviceBayTable(DeviceComponentTable):
}
)
status = tables.TemplateColumn(
template_code=DEVICEBAY_STATUS
template_code=DEVICEBAY_STATUS,
order_by=Accessor('installed_device__status')
)
installed_device = tables.Column(
linkify=True
Expand Down
10 changes: 9 additions & 1 deletion netbox/dcim/tables/racks.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,20 @@ class RackTable(BaseTable):
tags = TagColumn(
url_name='dcim:rack_list'
)
outer_width = tables.TemplateColumn(
template_code="{{ record.outer_width }} {{ record.outer_unit }}",
verbose_name='Outer Width'
)
outer_depth = tables.TemplateColumn(
template_code="{{ record.outer_depth }} {{ record.outer_unit }}",
verbose_name='Outer Depth'
)

class Meta(BaseTable.Meta):
model = Rack
fields = (
'pk', 'id', 'name', 'site', 'location', 'status', 'facility_id', 'tenant', 'role', 'serial', 'asset_tag', 'type',
'width', 'u_height', 'comments', 'device_count', 'get_utilization', 'get_power_utilization', 'tags',
'width', 'outer_width', 'outer_depth', 'u_height', 'comments', 'device_count', 'get_utilization', 'get_power_utilization', 'tags',
)
default_columns = (
'pk', 'name', 'site', 'location', 'status', 'facility_id', 'tenant', 'role', 'u_height', 'device_count',
Expand Down
18 changes: 7 additions & 11 deletions netbox/dcim/tables/template_code.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,13 @@

INTERFACE_IPADDRESSES = """
<div class="table-badge-group">
{% for ip in record.ip_addresses.all %}
<a
class="table-badge{% if ip.status != 'active' %} badge bg-{{ ip.get_status_class }}{% elif ip.role %} badge bg-{{ ip.get_role_class }}{% endif %}"
href="{{ ip.get_absolute_url }}"
{% if ip.status != 'active'%}data-bs-toggle="tooltip" data-bs-placement="left" title="{{ ip.get_status_display }}"
{% elif ip.role %}data-bs-toggle="tooltip" data-bs-placement="left" title="{{ ip.get_role_display }}"
{% endif %}
>
{{ ip }}
</a>
{% endfor %}
{% for ip in record.ip_addresses.all %}
{% if ip.status != 'active' %}
<a href="{{ ip.get_absolute_url }}" class="table-badge badge bg-{{ ip.get_status_class }}" data-bs-toggle="tooltip" data-bs-placement="left" title="{{ ip.get_status_display }}">{{ ip }}</a>
{% else %}
<a href="{{ ip.get_absolute_url }}" class="table-badge">{{ ip }}</a>
{% endif %}
{% endfor %}
</div>
"""

Expand Down
2 changes: 1 addition & 1 deletion netbox/extras/forms/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ class Meta:
class ExportTemplateForm(BootstrapMixin, forms.ModelForm):
content_type = ContentTypeChoiceField(
queryset=ContentType.objects.all(),
limit_choices_to=FeatureQuery('custom_links')
limit_choices_to=FeatureQuery('export_templates')
)

class Meta:
Expand Down
2 changes: 1 addition & 1 deletion netbox/extras/models/customfields.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def get_for_model(self, model):
return self.get_queryset().filter(content_types=content_type)


@extras_features('webhooks')
@extras_features('webhooks', 'export_templates')
class CustomField(ChangeLoggedModel):
content_types = models.ManyToManyField(
to=ContentType,
Expand Down
10 changes: 6 additions & 4 deletions netbox/extras/models/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from django.http import HttpResponse
from django.urls import reverse
from django.utils import timezone
from django.utils.formats import date_format, time_format
from django.utils.formats import date_format
from rest_framework.utils.encoders import JSONEncoder

from extras.choices import *
Expand All @@ -36,7 +36,7 @@
# Webhooks
#

@extras_features('webhooks')
@extras_features('webhooks', 'export_templates')
class Webhook(ChangeLoggedModel):
"""
A Webhook defines a request that will be sent to a remote application when an object is created, updated, and/or
Expand Down Expand Up @@ -175,7 +175,7 @@ def render_body(self, context):
# Custom links
#

@extras_features('webhooks')
@extras_features('webhooks', 'export_templates')
class CustomLink(ChangeLoggedModel):
"""
A custom link to an external representation of a NetBox object. The link text and URL fields accept Jinja2 template
Expand Down Expand Up @@ -234,7 +234,7 @@ def get_absolute_url(self):
# Export templates
#

@extras_features('webhooks')
@extras_features('webhooks', 'export_templates')
class ExportTemplate(ChangeLoggedModel):
content_type = models.ForeignKey(
to=ContentType,
Expand Down Expand Up @@ -357,6 +357,8 @@ class ImageAttachment(BigIDModel):

objects = RestrictedQuerySet.as_manager()

clone_fields = ('content_type', 'object_id')

class Meta:
ordering = ('name', 'pk') # name may be non-unique

Expand Down
2 changes: 1 addition & 1 deletion netbox/extras/models/tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
# Tags
#

@extras_features('webhooks')
@extras_features('webhooks', 'export_templates')
class Tag(ChangeLoggedModel, TagBase):
color = ColorField(
default=ColorChoices.COLOR_GREY
Expand Down
6 changes: 1 addition & 5 deletions netbox/extras/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -475,11 +475,7 @@ class ImageAttachmentEditView(generic.ObjectEditView):
def alter_obj(self, instance, request, args, kwargs):
if not instance.pk:
# Assign the parent object based on URL kwargs
try:
app_label, model = request.GET.get('content_type').split('.')
except (AttributeError, ValueError):
raise Http404("Content type not specified")
content_type = get_object_or_404(ContentType, app_label=app_label, model=model)
content_type = get_object_or_404(ContentType, pk=request.GET.get('content_type'))
instance.parent = get_object_or_404(content_type.model_class(), pk=request.GET.get('object_id'))
return instance

Expand Down
7 changes: 6 additions & 1 deletion netbox/ipam/forms/filtersets.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import django_filters
from django import forms
from django.utils.translation import gettext as _

Expand Down Expand Up @@ -409,7 +410,7 @@ class VLANFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldModelFilterFo
field_groups = [
['q', 'tag'],
['region_id', 'site_group_id', 'site_id'],
['group_id', 'status', 'role_id'],
['group_id', 'status', 'role_id', 'vid'],
['tenant_group_id', 'tenant_id'],
]
q = forms.CharField(
Expand Down Expand Up @@ -461,6 +462,10 @@ class VLANFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldModelFilterFo
label=_('Role'),
fetch_trigger='open'
)
vid = forms.IntegerField(
required=False,
label='VLAN ID'
)
tag = TagFilterField(model)


Expand Down
2 changes: 1 addition & 1 deletion netbox/ipam/tables/vlans.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ class VLANTable(BaseTable):
pk = ToggleColumn()
vid = tables.TemplateColumn(
template_code=VLAN_LINK,
verbose_name='ID'
verbose_name='VID'
)
site = tables.Column(
linkify=True
Expand Down
Loading

0 comments on commit b29a551

Please sign in to comment.