Merge branch 'develop' into feature

This commit is contained in:
jeremystretch 2022-12-08 09:31:22 -05:00
commit 5a77791f9d
11 changed files with 47 additions and 13 deletions

View File

@ -225,6 +225,9 @@ Once NetBox has been configured, we're ready to proceed with the actual installa
* Builds the documentation locally (for offline use) * Builds the documentation locally (for offline use)
* Aggregate static resource files on disk * Aggregate static resource files on disk
!!! warning
If you still have a Python virtual environment active from a previous installation step, disable it now by running the `deactivate` command. This will avoid errors on systems where `sudo` has been configured to preserve the user's current environment.
```no-highlight ```no-highlight
sudo /opt/netbox/upgrade.sh sudo /opt/netbox/upgrade.sh
``` ```

View File

@ -2,6 +2,18 @@
## v3.3.10 (FUTURE) ## v3.3.10 (FUTURE)
### Enhancements
* [#10748](https://github.com/netbox-community/netbox/issues/10748) - Add provider selection field for provider networks to circuit termination edit view
* [#11119](https://github.com/netbox-community/netbox/issues/11119) - Enable filtering L2VPNs by slug
### Bug Fixes
* [#11041](https://github.com/netbox-community/netbox/issues/11041) - Correct power utilization percentage precision
* [#11087](https://github.com/netbox-community/netbox/issues/11087) - Fix background color of bottom banner content
* [#11101](https://github.com/netbox-community/netbox/issues/11101) - Correct circuits count under site view
* [#11128](https://github.com/netbox-community/netbox/issues/11128) - Disable ordering changelog table by object to avoid exception
--- ---
## v3.3.9 (2022-11-30) ## v3.3.9 (2022-11-30)

View File

@ -145,16 +145,28 @@ class CircuitTerminationForm(NetBoxModelForm):
}, },
required=False required=False
) )
provider_network_provider = DynamicModelChoiceField(
queryset=Provider.objects.all(),
required=False,
label='Provider',
initial_params={
'networks': 'provider_network'
}
)
provider_network = DynamicModelChoiceField( provider_network = DynamicModelChoiceField(
queryset=ProviderNetwork.objects.all(), queryset=ProviderNetwork.objects.all(),
query_params={
'provider_id': '$provider_network_provider',
},
required=False required=False
) )
class Meta: class Meta:
model = CircuitTermination model = CircuitTermination
fields = [ fields = [
'provider', 'circuit', 'term_side', 'region', 'site_group', 'site', 'provider_network', 'mark_connected', 'provider', 'circuit', 'term_side', 'region', 'site_group', 'site', 'provider_network_provider',
'port_speed', 'upstream_speed', 'xconnect_id', 'pp_info', 'description', 'tags', 'provider_network', 'mark_connected', 'port_speed', 'upstream_speed', 'xconnect_id', 'pp_info',
'description', 'tags',
] ]
help_texts = { help_texts = {
'port_speed': _("Physical circuit speed"), 'port_speed': _("Physical circuit speed"),

View File

@ -391,7 +391,7 @@ class SiteView(generic.ObjectView):
scope_id=instance.pk scope_id=instance.pk
).count(), ).count(),
'vlan_count': VLAN.objects.restrict(request.user, 'view').filter(site=instance).count(), 'vlan_count': VLAN.objects.restrict(request.user, 'view').filter(site=instance).count(),
'circuit_count': Circuit.objects.restrict(request.user, 'view').filter(terminations__site=instance).count(), 'circuit_count': Circuit.objects.restrict(request.user, 'view').filter(terminations__site=instance).distinct().count(),
'vm_count': VirtualMachine.objects.restrict(request.user, 'view').filter(cluster__site=instance).count(), 'vm_count': VirtualMachine.objects.restrict(request.user, 'view').filter(cluster__site=instance).count(),
} }
locations = Location.objects.add_related_count( locations = Location.objects.add_related_count(

View File

@ -215,7 +215,8 @@ class ObjectChangeTable(NetBoxTable):
object_repr = tables.TemplateColumn( object_repr = tables.TemplateColumn(
accessor=tables.A('changed_object'), accessor=tables.A('changed_object'),
template_code=OBJECTCHANGE_OBJECT, template_code=OBJECTCHANGE_OBJECT,
verbose_name='Object' verbose_name='Object',
orderable=False
) )
request_id = tables.TemplateColumn( request_id = tables.TemplateColumn(
template_code=OBJECTCHANGE_REQUEST_ID, template_code=OBJECTCHANGE_REQUEST_ID,

View File

@ -962,7 +962,7 @@ class L2VPNFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
class Meta: class Meta:
model = L2VPN model = L2VPN
fields = ['id', 'identifier', 'name', 'type', 'description'] fields = ['id', 'identifier', 'name', 'slug', 'type', 'description']
def search(self, queryset, name, value): def search(self, queryset, name, value):
if not value.strip(): if not value.strip():

View File

@ -1505,6 +1505,10 @@ class L2VPNTestCase(TestCase, ChangeLoggedFilterSetTests):
params = {'name': ['L2VPN 1', 'L2VPN 2']} params = {'name': ['L2VPN 1', 'L2VPN 2']}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
def test_slug(self):
params = {'slug': ['l2vpn-1', 'l2vpn-2']}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
def test_identifier(self): def test_identifier(self):
params = {'identifier': ['65001', '65002']} params = {'identifier': ['65001', '65002']}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)

View File

@ -102,14 +102,14 @@ Blocks:
{% block content %}{% endblock %} {% block content %}{% endblock %}
</div> </div>
{% endblock %} {% endblock %}
{# Bottom banner #}
{% if config.BANNER_BOTTOM %}
<div class="text-center mx-3">
{{ config.BANNER_BOTTOM|safe }}
</div>
{% endif %}
</div> </div>
{% if config.BANNER_BOTTOM %}
<div class="text-center mx-3">
{{ config.BANNER_BOTTOM|safe }}
</div>
{% endif %}
{# BS5 pop-up modals #} {# BS5 pop-up modals #}
{% block modals %}{% endblock %} {% block modals %}{% endblock %}

View File

@ -32,6 +32,7 @@
{% render_field form.site %} {% render_field form.site %}
</div> </div>
<div class="tab-pane{% if providernetwork_tab_active %} active{% endif %}" id="providernetwork"> <div class="tab-pane{% if providernetwork_tab_active %} active{% endif %}" id="providernetwork">
{% render_field form.provider_network_provider %}
{% render_field form.provider_network %} {% render_field form.provider_network %}
</div> </div>
</div> </div>

View File

@ -81,7 +81,7 @@
{% else %} {% else %}
<tr> <tr>
<td>Provider Network</td> <td>Provider Network</td>
<td>{{ termination.provider_network|linkify }}</td> <td>{{ termination.provider_network.provider|linkify }} / {{ termination.provider_network|linkify }}</td>
</tr> </tr>
{% endif %} {% endif %}
<tr> <tr>

View File

@ -140,7 +140,8 @@ def percentage(x, y):
""" """
if x is None or y is None: if x is None or y is None:
return None return None
return round(x / y * 100)
return round(x / y * 100, 1)
@register.filter() @register.filter()