mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-14 09:51:22 -06:00
Merge branch 'develop' into feature
This commit is contained in:
commit
5a77791f9d
@ -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
|
||||||
```
|
```
|
||||||
|
@ -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)
|
||||||
|
@ -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"),
|
||||||
|
@ -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(
|
||||||
|
@ -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,
|
||||||
|
@ -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():
|
||||||
|
@ -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)
|
||||||
|
@ -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 %}
|
||||||
|
|
||||||
|
@ -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>
|
||||||
|
@ -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>
|
||||||
|
@ -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()
|
||||||
|
Loading…
Reference in New Issue
Block a user