From 4132027ada8344fd2125562ac4331b3bc1fdfcaa Mon Sep 17 00:00:00 2001 From: Arthur Hanson Date: Wed, 24 Aug 2022 14:12:14 -0700 Subject: [PATCH 1/7] fixes for #10070 make l2vpn slug unique (#10119) Co-authored-by: jeremystretch --- .../ipam/migrations/0060_alter_l2vpn_slug.py | 18 ++++++++++++++++++ netbox/ipam/models/l2vpn.py | 5 ++++- 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 netbox/ipam/migrations/0060_alter_l2vpn_slug.py diff --git a/netbox/ipam/migrations/0060_alter_l2vpn_slug.py b/netbox/ipam/migrations/0060_alter_l2vpn_slug.py new file mode 100644 index 000000000..9e70c2063 --- /dev/null +++ b/netbox/ipam/migrations/0060_alter_l2vpn_slug.py @@ -0,0 +1,18 @@ +# Generated by Django 4.0.7 on 2022-08-22 15:58 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('ipam', '0059_l2vpn'), + ] + + operations = [ + migrations.AlterField( + model_name='l2vpn', + name='slug', + field=models.SlugField(max_length=100, unique=True), + ), + ] diff --git a/netbox/ipam/models/l2vpn.py b/netbox/ipam/models/l2vpn.py index 9718e9cab..a457f334b 100644 --- a/netbox/ipam/models/l2vpn.py +++ b/netbox/ipam/models/l2vpn.py @@ -21,7 +21,10 @@ class L2VPN(NetBoxModel): max_length=100, unique=True ) - slug = models.SlugField() + slug = models.SlugField( + max_length=100, + unique=True + ) type = models.CharField( max_length=50, choices=L2VPNTypeChoices From 6c686af1b70acdc56a8fdbe84451f7012e2b4197 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Wed, 24 Aug 2022 17:13:09 -0400 Subject: [PATCH 2/7] Changelog for #10070 --- docs/release-notes/version-3.3.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/release-notes/version-3.3.md b/docs/release-notes/version-3.3.md index 1421bb2c7..a1ac5b40f 100644 --- a/docs/release-notes/version-3.3.md +++ b/docs/release-notes/version-3.3.md @@ -20,6 +20,7 @@ * [#10055](https://github.com/netbox-community/netbox/issues/10055) - Fix extraneous NAT indicator by device primary IP * [#10057](https://github.com/netbox-community/netbox/issues/10057) - Fix AttributeError exception when global search results include rack reservations * [#10059](https://github.com/netbox-community/netbox/issues/10059) - Add identifier column to L2VPN table +* [#10070](https://github.com/netbox-community/netbox/issues/10070) - Add unique constraint for L2VPN slug * [#10089](https://github.com/netbox-community/netbox/issues/10089) - `linkify` template filter should escape object representation * [#10094](https://github.com/netbox-community/netbox/issues/10094) - Fix 404 when using "create and add another" to add contact assignments * [#10108](https://github.com/netbox-community/netbox/issues/10108) - Linkify inside NAT IPs for primary device IPs in UI From ec2e8ad18466f024ad6bb22c3412b6dd69ede4c5 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Date: Thu, 25 Aug 2022 05:21:55 -0700 Subject: [PATCH 3/7] #10139 update development documents for githooks and web-ui (#10141) * #10139 update development documents for githooks and web-ui * Remove redudant phrase Co-authored-by: Jeremy Stretch --- docs/development/getting-started.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/development/getting-started.md b/docs/development/getting-started.md index 38d521de6..bac2b4dca 100644 --- a/docs/development/getting-started.md +++ b/docs/development/getting-started.md @@ -54,6 +54,12 @@ NetBox ships with a [git pre-commit hook](https://githooks.com/) script that aut cd .git/hooks/ ln -s ../../scripts/git-hooks/pre-commit ``` +For the pre-commit hooks to work, you will also need to install the pycodestyle package: + +```no-highlight +python -m pip install pycodestyle +``` +...and setup the yarn packages as shown in the [Web UI Development Guide](web-ui.md) ### 3. Create a Python Virtual Environment @@ -118,6 +124,10 @@ This ensures that your development environment is now complete and operational. !!! tip "IDE Integration" Some IDEs, such as the highly-recommended [PyCharm](https://www.jetbrains.com/pycharm/), will integrate with Django's development server and allow you to run it directly within the IDE. This is strongly encouraged as it makes for a much more convenient development environment. +## UI Development + +For UI development you will need to review the [Web UI Development Guide](web-ui.md) + ## Populating Demo Data Once you have your development environment up and running, it might be helpful to populate some "dummy" data to make interacting with the UI and APIs more convenient. Check out the [netbox-demo-data](https://github.com/netbox-community/netbox-demo-data) repo on GitHub, which houses a collection of sample data that can be easily imported to any new NetBox deployment. (This sample data is used to populate the public demo instance at .) From 482b4b6e95ce4e32eba2ceb38b359fb66d65e4ee Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Thu, 25 Aug 2022 08:37:43 -0400 Subject: [PATCH 4/7] Fixes #10147: Permit the creation of 0U device types via REST API --- docs/release-notes/version-3.3.md | 1 + netbox/dcim/api/serializers.py | 2 +- netbox/dcim/tests/test_api.py | 3 +++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/release-notes/version-3.3.md b/docs/release-notes/version-3.3.md index a1ac5b40f..6e8846e4a 100644 --- a/docs/release-notes/version-3.3.md +++ b/docs/release-notes/version-3.3.md @@ -27,6 +27,7 @@ * [#10109](https://github.com/netbox-community/netbox/issues/10109) - Fix available prefixes calculation for container prefixes in the global table * [#10111](https://github.com/netbox-community/netbox/issues/10111) - Wrap search QS to catch ValueError on identifier field * [#10134](https://github.com/netbox-community/netbox/issues/10134) - Custom fields data serializer should return a 400 response for invalid data +* [#10147](https://github.com/netbox-community/netbox/issues/10147) - Permit the creation of 0U device types via REST API --- diff --git a/netbox/dcim/api/serializers.py b/netbox/dcim/api/serializers.py index 249a3f167..af806acb8 100644 --- a/netbox/dcim/api/serializers.py +++ b/netbox/dcim/api/serializers.py @@ -310,7 +310,7 @@ class DeviceTypeSerializer(NetBoxModelSerializer): max_digits=4, decimal_places=1, label='Position (U)', - min_value=decimal.Decimal(0.5), + min_value=0, default=1.0 ) subdevice_role = ChoiceField(choices=SubdeviceRoleChoices, allow_blank=True, required=False) diff --git a/netbox/dcim/tests/test_api.py b/netbox/dcim/tests/test_api.py index a78a98ae5..acd52178d 100644 --- a/netbox/dcim/tests/test_api.py +++ b/netbox/dcim/tests/test_api.py @@ -461,16 +461,19 @@ class DeviceTypeTest(APIViewTestCases.APIViewTestCase): 'manufacturer': manufacturers[1].pk, 'model': 'Device Type 4', 'slug': 'device-type-4', + 'u_height': 0, }, { 'manufacturer': manufacturers[1].pk, 'model': 'Device Type 5', 'slug': 'device-type-5', + 'u_height': 0.5, }, { 'manufacturer': manufacturers[1].pk, 'model': 'Device Type 6', 'slug': 'device-type-6', + 'u_height': 1, }, ] From 9da9a209a5e0935b4ba1460fbfffa1850f45e844 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 25 Aug 2022 08:46:19 -0400 Subject: [PATCH 5/7] Fixes #10087: Correct display of far end in console/power/interface connections tables (#10117) --- docs/release-notes/version-3.3.md | 1 + netbox/dcim/tables/__init__.py | 103 +----------------------------- netbox/dcim/tables/connections.py | 71 ++++++++++++++++++++ netbox/dcim/views.py | 6 +- 4 files changed, 76 insertions(+), 105 deletions(-) create mode 100644 netbox/dcim/tables/connections.py diff --git a/docs/release-notes/version-3.3.md b/docs/release-notes/version-3.3.md index 6e8846e4a..741fdc8d5 100644 --- a/docs/release-notes/version-3.3.md +++ b/docs/release-notes/version-3.3.md @@ -21,6 +21,7 @@ * [#10057](https://github.com/netbox-community/netbox/issues/10057) - Fix AttributeError exception when global search results include rack reservations * [#10059](https://github.com/netbox-community/netbox/issues/10059) - Add identifier column to L2VPN table * [#10070](https://github.com/netbox-community/netbox/issues/10070) - Add unique constraint for L2VPN slug +* [#10087](https://github.com/netbox-community/netbox/issues/10087) - Correct display of far end in console/power/interface connections tables * [#10089](https://github.com/netbox-community/netbox/issues/10089) - `linkify` template filter should escape object representation * [#10094](https://github.com/netbox-community/netbox/issues/10094) - Fix 404 when using "create and add another" to add contact assignments * [#10108](https://github.com/netbox-community/netbox/issues/10108) - Linkify inside NAT IPs for primary device IPs in UI diff --git a/netbox/dcim/tables/__init__.py b/netbox/dcim/tables/__init__.py index e3b2a42ba..843b612b1 100644 --- a/netbox/dcim/tables/__init__.py +++ b/netbox/dcim/tables/__init__.py @@ -1,109 +1,8 @@ -import django_tables2 as tables -from django_tables2.utils import Accessor - -from netbox.tables import BaseTable, columns -from dcim.models import ConsolePort, Interface, PowerPort from .cables import * +from .connections import * from .devices import * from .devicetypes import * from .modules import * from .power import * from .racks import * from .sites import * - - -# -# Device connections -# - -class ConsoleConnectionTable(BaseTable): - console_server = tables.Column( - accessor=Accessor('_path__destination__device'), - orderable=False, - linkify=True, - verbose_name='Console Server' - ) - console_server_port = tables.Column( - accessor=Accessor('_path__destination'), - orderable=False, - linkify=True, - verbose_name='Port' - ) - device = tables.Column( - linkify=True - ) - name = tables.Column( - linkify=True, - verbose_name='Console Port' - ) - reachable = columns.BooleanColumn( - accessor=Accessor('_path__is_active'), - verbose_name='Reachable' - ) - - class Meta(BaseTable.Meta): - model = ConsolePort - fields = ('device', 'name', 'console_server', 'console_server_port', 'reachable') - - -class PowerConnectionTable(BaseTable): - pdu = tables.Column( - accessor=Accessor('_path__destination__device'), - orderable=False, - linkify=True, - verbose_name='PDU' - ) - outlet = tables.Column( - accessor=Accessor('_path__destination'), - orderable=False, - linkify=True, - verbose_name='Outlet' - ) - device = tables.Column( - linkify=True - ) - name = tables.Column( - linkify=True, - verbose_name='Power Port' - ) - reachable = columns.BooleanColumn( - accessor=Accessor('_path__is_active'), - verbose_name='Reachable' - ) - - class Meta(BaseTable.Meta): - model = PowerPort - fields = ('device', 'name', 'pdu', 'outlet', 'reachable') - - -class InterfaceConnectionTable(BaseTable): - device_a = tables.Column( - accessor=Accessor('device'), - linkify=True, - verbose_name='Device A' - ) - interface_a = tables.Column( - accessor=Accessor('name'), - linkify=True, - verbose_name='Interface A' - ) - device_b = tables.Column( - accessor=Accessor('_path__destination__device'), - orderable=False, - linkify=True, - verbose_name='Device B' - ) - interface_b = tables.Column( - accessor=Accessor('_path__destination'), - orderable=False, - linkify=True, - verbose_name='Interface B' - ) - reachable = columns.BooleanColumn( - accessor=Accessor('_path__is_active'), - verbose_name='Reachable' - ) - - class Meta(BaseTable.Meta): - model = Interface - fields = ('device_a', 'interface_a', 'device_b', 'interface_b', 'reachable') diff --git a/netbox/dcim/tables/connections.py b/netbox/dcim/tables/connections.py new file mode 100644 index 000000000..f9f78f3a6 --- /dev/null +++ b/netbox/dcim/tables/connections.py @@ -0,0 +1,71 @@ +import django_tables2 as tables +from django_tables2.utils import Accessor + +from netbox.tables import BaseTable, columns +from dcim.models import ConsolePort, Interface, PowerPort +from .devices import PathEndpointTable + +__all__ = ( + 'ConsoleConnectionTable', + 'InterfaceConnectionTable', + 'PowerConnectionTable', +) + + +# +# Device connections +# + +class ConsoleConnectionTable(PathEndpointTable): + device = tables.Column( + linkify=True + ) + name = tables.Column( + linkify=True, + verbose_name='Console Port' + ) + reachable = columns.BooleanColumn( + accessor=Accessor('_path__is_active'), + verbose_name='Reachable' + ) + + class Meta(BaseTable.Meta): + model = ConsolePort + fields = ('device', 'name', 'connection', 'reachable') + + +class PowerConnectionTable(PathEndpointTable): + device = tables.Column( + linkify=True + ) + name = tables.Column( + linkify=True, + verbose_name='Power Port' + ) + reachable = columns.BooleanColumn( + accessor=Accessor('_path__is_active'), + verbose_name='Reachable' + ) + + class Meta(BaseTable.Meta): + model = PowerPort + fields = ('device', 'name', 'connection', 'reachable') + + +class InterfaceConnectionTable(PathEndpointTable): + device = tables.Column( + accessor=Accessor('device'), + linkify=True + ) + interface = tables.Column( + accessor=Accessor('name'), + linkify=True + ) + reachable = columns.BooleanColumn( + accessor=Accessor('_path__is_active'), + verbose_name='Reachable' + ) + + class Meta(BaseTable.Meta): + model = Interface + fields = ('device', 'interface', 'connection', 'reachable') diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index a31eabc5e..39b2340e1 100644 --- a/netbox/dcim/views.py +++ b/netbox/dcim/views.py @@ -2893,7 +2893,7 @@ class CableBulkDeleteView(generic.BulkDeleteView): # class ConsoleConnectionsListView(generic.ObjectListView): - queryset = ConsolePort.objects.filter(_path__isnull=False).order_by('device') + queryset = ConsolePort.objects.filter(_path__is_complete=True) filterset = filtersets.ConsoleConnectionFilterSet filterset_form = forms.ConsoleConnectionFilterForm table = tables.ConsoleConnectionTable @@ -2907,7 +2907,7 @@ class ConsoleConnectionsListView(generic.ObjectListView): class PowerConnectionsListView(generic.ObjectListView): - queryset = PowerPort.objects.filter(_path__isnull=False).order_by('device') + queryset = PowerPort.objects.filter(_path__is_complete=True) filterset = filtersets.PowerConnectionFilterSet filterset_form = forms.PowerConnectionFilterForm table = tables.PowerConnectionTable @@ -2921,7 +2921,7 @@ class PowerConnectionsListView(generic.ObjectListView): class InterfaceConnectionsListView(generic.ObjectListView): - queryset = Interface.objects.filter(_path__isnull=False).order_by('device') + queryset = Interface.objects.filter(_path__is_complete=True) filterset = filtersets.InterfaceConnectionFilterSet filterset_form = forms.InterfaceConnectionFilterForm table = tables.InterfaceConnectionTable From 5f37699736a892e59dbe8ee5a58aaf6e588be0ec Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Thu, 25 Aug 2022 10:34:18 -0400 Subject: [PATCH 6/7] Fixes #9663: Omit available IP annotations when filtering prefix child IPs list --- docs/release-notes/version-3.3.md | 1 + netbox/ipam/views.py | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/release-notes/version-3.3.md b/docs/release-notes/version-3.3.md index 741fdc8d5..7b23e242b 100644 --- a/docs/release-notes/version-3.3.md +++ b/docs/release-notes/version-3.3.md @@ -15,6 +15,7 @@ ### Bug Fixes +* [#9663](https://github.com/netbox-community/netbox/issues/9663) - Omit available IP annotations when filtering prefix child IPs list * [#10040](https://github.com/netbox-community/netbox/issues/10040) - Fix exception when ordering prefixes by flat representation * [#10053](https://github.com/netbox-community/netbox/issues/10053) - Custom fields header should not be displayed when editing circuit terminations with no custom fields * [#10055](https://github.com/netbox-community/netbox/issues/10055) - Fix extraneous NAT indicator by device primary IP diff --git a/netbox/ipam/views.py b/netbox/ipam/views.py index a086ab66d..185154ffb 100644 --- a/netbox/ipam/views.py +++ b/netbox/ipam/views.py @@ -526,8 +526,7 @@ class PrefixIPAddressesView(generic.ObjectChildrenView): return parent.get_child_ips().restrict(request.user, 'view').prefetch_related('vrf', 'tenant', 'tenant__group') def prep_table_data(self, request, queryset, parent): - show_available = bool(request.GET.get('show_available', 'true') == 'true') - if show_available: + if not request.GET.get('q'): return add_available_ipaddresses(parent.prefix, queryset, parent.is_pool) return queryset From bb37ebf4bacafb4334b3ad2096467a1dda39086e Mon Sep 17 00:00:00 2001 From: Arthur Hanson Date: Thu, 25 Aug 2022 10:38:55 -0700 Subject: [PATCH 7/7] #10038 add assign FHRP group to device-interface context menu (#10151) --- netbox/dcim/tables/template_code.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/netbox/dcim/tables/template_code.py b/netbox/dcim/tables/template_code.py index 8c23f327c..18ff8b7b6 100644 --- a/netbox/dcim/tables/template_code.py +++ b/netbox/dcim/tables/template_code.py @@ -241,6 +241,9 @@ INTERFACE_BUTTONS = """ {% if perms.dcim.add_interface %}
  • Child Interface
  • {% endif %} + {% if perms.ipam.add_fhrpgroupassignment %} +
  • Assign FHRP Group
  • + {% endif %} {% endif %}