GithubHelp home page GithubHelp logo

auroraresearchlab / netbox-dns Goto Github PK

View Code? Open in Web Editor NEW
209.0 209.0 20.0 7.45 MB

Netbox Dns is a netbox plugin for managing zone, nameserver and record inventory.

License: MIT License

Python 94.43% HTML 5.57%
dns netbox netbox-plugin

netbox-dns's People

Contributors

hatsat32 avatar hbasria avatar jeremystretch avatar levensailor avatar lupo avatar peteeckel avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

netbox-dns's Issues

Netbox DNS does not show up in Web UI

Hi. I just installed netbox-dns plugin.
After installing I run collectstatic and migrate commands on manage.py, than restarted services.
Everything looks fine but there is nothing on plugins menu on Web UI.
Inside Django Admin there is a Netbox DNS section, but not in main web UI.

Netbox: 3.0.3 (fresh install)
Python 3.9.2
CentOS 8

I also have installed secretstore, Qr-code and topology-views plugins. Just to be noted.

Improve filtering for Zones, NameServers and Records

Minor and moderate issues with filters:

  • Nameserver filtering has a "Search" field that is supposed to search in "All Fields", but actually it only searches in the name field.
  • Record filtering has the same search field, but it only searches in the name field as well and not in value or zone fields (which would make a lot of sense).

django.db.utils.OperationalError: cannot CREATE INDEX "netbox_dns_record" because it has pending trigger events

ENV

Netbox: 3.0.11
Python: 3.8.11
PostgreSQL: 10.19

When i upgrade netbox, the following error occurred:

Operations to perform:
  Apply all migrations: admin, auth, circuits, contenttypes, dcim, django_rq, extras, ipam, netbox_dns, sessions, taggit, tenancy, users, virtualization
Running migrations:
  Applying netbox_dns.0004_create_ptr_for_a_aaaa_records...Traceback (most recent call last):
  File "/opt/netbox-3.0.11/venv/lib64/python3.8/site-packages/django/db/backends/utils.py", line 82, in _execute
    return self.cursor.execute(sql)
psycopg2.errors.ObjectInUse: cannot CREATE INDEX "netbox_dns_record" because it has pending trigger events


The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "./manage.py", line 10, in <module>
    execute_from_command_line(sys.argv)
  File "/opt/netbox-3.0.11/venv/lib64/python3.8/site-packages/django/core/management/__init__.py", line 419, in execute_from_command_line
    utility.execute()
  File "/opt/netbox-3.0.11/venv/lib64/python3.8/site-packages/django/core/management/__init__.py", line 413, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/opt/netbox-3.0.11/venv/lib64/python3.8/site-packages/django/core/management/base.py", line 354, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/opt/netbox-3.0.11/venv/lib64/python3.8/site-packages/django/core/management/base.py", line 398, in execute
    output = self.handle(*args, **options)
  File "/opt/netbox-3.0.11/venv/lib64/python3.8/site-packages/django/core/management/base.py", line 89, in wrapped
    res = handle_func(*args, **kwargs)
  File "/opt/netbox-3.0.11/venv/lib64/python3.8/site-packages/django/core/management/commands/migrate.py", line 244, in handle
    post_migrate_state = executor.migrate(
  File "/opt/netbox-3.0.11/venv/lib64/python3.8/site-packages/django/db/migrations/executor.py", line 117, in migrate
    state = self._migrate_all_forwards(state, plan, full_plan, fake=fake, fake_initial=fake_initial)
  File "/opt/netbox-3.0.11/venv/lib64/python3.8/site-packages/django/db/migrations/executor.py", line 147, in _migrate_all_forwards
    state = self.apply_migration(state, migration, fake=fake, fake_initial=fake_initial)
  File "/opt/netbox-3.0.11/venv/lib64/python3.8/site-packages/django/db/migrations/executor.py", line 227, in apply_migration
    state = migration.apply(state, schema_editor)
  File "/opt/netbox-3.0.11/venv/lib64/python3.8/site-packages/django/db/migrations/migration.py", line 126, in apply
    operation.database_forwards(self.app_label, schema_editor, old_state, project_state)
  File "/opt/netbox-3.0.11/venv/lib64/python3.8/site-packages/django/db/migrations/operations/models.py", line 858, in database_forwards
    schema_editor.add_constraint(model, self.constraint)
  File "/opt/netbox-3.0.11/venv/lib64/python3.8/site-packages/django/db/backends/base/schema.py", line 397, in add_constraint
    self.execute(sql, params=None)
  File "/opt/netbox-3.0.11/venv/lib64/python3.8/site-packages/django/db/backends/base/schema.py", line 145, in execute
    cursor.execute(sql, params)
  File "/opt/netbox-3.0.11/venv/lib64/python3.8/site-packages/django/db/backends/utils.py", line 66, in execute
    return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
  File "/opt/netbox-3.0.11/venv/lib64/python3.8/site-packages/django/db/backends/utils.py", line 75, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "/opt/netbox-3.0.11/venv/lib64/python3.8/site-packages/django/db/backends/utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
  File "/opt/netbox-3.0.11/venv/lib64/python3.8/site-packages/django/db/utils.py", line 90, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/opt/netbox-3.0.11/venv/lib64/python3.8/site-packages/django/db/backends/utils.py", line 82, in _execute
    return self.cursor.execute(sql)
django.db.utils.OperationalError: cannot CREATE INDEX "netbox_dns_record" because it has pending trigger events

Try to modify netbox_dns/migrations/0004_create_ptr_for_a_aaaa_records.py, add the following on line 26

     atomic = False

Run manage.py migrate successfully.

Deleting a zone with address records fails

When a zone that has A or AAAA records with automatic PTR record generation is deleted, under certain circumstances the deletion fails with the following error message:

Traceback (most recent call last):
  File "/opt/netbox/lib/python3.8/site-packages/django/template/base.py", line 848, in _resolve_lookup
    raise VariableDoesNotExist("Failed lookup for key "
django.template.base.VariableDoesNotExist: Failed lookup for key [page] in <netbox_dns.tables.ZoneTable object at 0x7fe1c1a08220>
Internal Server Error: /plugins/netbox_dns/zones/delete/
Traceback (most recent call last):
  File "/opt/netbox/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/opt/netbox/lib/python3.8/site-packages/django/core/handlers/base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/opt/netbox/lib/python3.8/site-packages/django/views/generic/base.py", line 70, in view
    return self.dispatch(request, *args, **kwargs)
  File "/opt/netbox/netbox/utilities/views.py", line 93, in dispatch
    return super().dispatch(request, *args, **kwargs)
  File "/opt/netbox/lib/python3.8/site-packages/django/views/generic/base.py", line 98, in dispatch
    return handler(request, *args, **kwargs)
  File "/opt/netbox/netbox/netbox/views/generic.py", line 1039, in post
    obj.delete()
  File "/opt/netbox/lib/python3.8/site-packages/netbox_dns/models.py", line 255, in delete
    record.update_ptr_record()
  File "/opt/netbox/lib/python3.8/site-packages/netbox_dns/models.py", line 453, in update_ptr_record
    super().save()
  File "/opt/netbox/lib/python3.8/site-packages/django/db/models/base.py", line 682, in save
    self._prepare_related_fields_for_save(operation_name='save')
  File "/opt/netbox/lib/python3.8/site-packages/django/db/models/base.py", line 932, in _prepare_related_fields_for_save
    raise ValueError(
ValueError: save() prohibited to prevent data loss due to unsaved related object 'zone'.
Exception while resolving variable 'request' in template 'home.html'.
Traceback (most recent call last):
  File "/opt/netbox/lib/python3.8/site-packages/django/template/base.py", line 829, in _resolve_lookup
    current = current[bit]
  File "/opt/netbox/lib/python3.8/site-packages/django/template/context.py", line 83, in __getitem__
    raise KeyError(key)
KeyError: 'request'

So far, I was only able to reproduce it in a development version of the plugin containing additional features, but the underlying bug is in the existing code in version 0.6.0.

BulkEdit is missing for NameServer objects

While currently of limited functionality (though it does come in handy when assigning tags), it would be useful to have the BulkEdit functionality available for NameServer objects, too - currently there is only BulkDelete.

Make the zone status field more useful

Following up on discussion #107, the zone status field needs a bit of attention.

The notion of a "passive" zone does not make much sense in the given context, and there are some other states that make sense, so the list of states a zone can have should be extended, e.g. to

  • Active
  • Reserved
  • Deprecated
  • Parked

When a zone is not marked "Active", this should have an impact on the creation of PTR records if there are any address records in the zone. At least they should get flagged as inactive so that provisioning mechanisms based on Netbox DNS data can handle them appropriately (probably just ignoring them).

plugin fails on netbox v3.1.1

Hello.
plugin doesn't work on version 3.1.1

<class 'django.urls.exceptions.NoReverseMatch'>
'netbox_dns' is not a registered namespace inside 'plugins'
Python version: 3.8.10
NetBox version: 3.1.1

And it fails on manage.py migrate

../venv/bin/python manage.py migrate 
Traceback (most recent call last):
  File "manage.py", line 10, in <module>
    execute_from_command_line(sys.argv)
  File "/opt/netbox-3.1.1/venv/lib/python3.8/site-packages/django/core/management/__init__.py", line 419, in execute_from_command_line
    utility.execute()
  File "/opt/netbox-3.1.1/venv/lib/python3.8/site-packages/django/core/management/__init__.py", line 413, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/opt/netbox-3.1.1/venv/lib/python3.8/site-packages/django/core/management/base.py", line 354, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/opt/netbox-3.1.1/venv/lib/python3.8/site-packages/django/core/management/base.py", line 398, in execute
    output = self.handle(*args, **options)
  File "/opt/netbox-3.1.1/venv/lib/python3.8/site-packages/django/core/management/base.py", line 89, in wrapped
    res = handle_func(*args, **kwargs)
  File "/opt/netbox-3.1.1/venv/lib/python3.8/site-packages/django/core/management/commands/migrate.py", line 75, in handle
    self.check(databases=[database])
  File "/opt/netbox-3.1.1/venv/lib/python3.8/site-packages/django/core/management/base.py", line 419, in check
    all_issues = checks.run_checks(
  File "/opt/netbox-3.1.1/venv/lib/python3.8/site-packages/django/core/checks/registry.py", line 76, in run_checks
    new_errors = check(app_configs=app_configs, databases=databases)
  File "/opt/netbox-3.1.1/venv/lib/python3.8/site-packages/django/core/checks/urls.py", line 13, in check_url_config
    return check_resolver(resolver)
  File "/opt/netbox-3.1.1/venv/lib/python3.8/site-packages/django/core/checks/urls.py", line 23, in check_resolver
    return check_method()
  File "/opt/netbox-3.1.1/venv/lib/python3.8/site-packages/django/urls/resolvers.py", line 416, in check
    for pattern in self.url_patterns:
  File "/opt/netbox-3.1.1/venv/lib/python3.8/site-packages/django/utils/functional.py", line 48, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/opt/netbox-3.1.1/venv/lib/python3.8/site-packages/django/urls/resolvers.py", line 602, in url_patterns
    patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
  File "/opt/netbox-3.1.1/venv/lib/python3.8/site-packages/django/utils/functional.py", line 48, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/opt/netbox-3.1.1/venv/lib/python3.8/site-packages/django/urls/resolvers.py", line 595, in urlconf_module
    return import_module(self.urlconf_name)
  File "/usr/lib/python3.8/importlib/__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1014, in _gcd_import
  File "<frozen importlib._bootstrap>", line 991, in _find_and_load
  File "<frozen importlib._bootstrap>", line 975, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 671, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 848, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "/opt/netbox-3.1.1/netbox/netbox/urls.py", line 9, in <module>
    from extras.plugins.urls import plugin_admin_patterns, plugin_patterns, plugin_api_patterns
  File "/opt/netbox-3.1.1/netbox/extras/plugins/urls.py", line 28, in <module>
    urlpatterns = import_object(f"{plugin_path}.urls.urlpatterns")
  File "/opt/netbox-3.1.1/netbox/extras/plugins/utils.py", line 31, in import_object
    spec.loader.exec_module(module)
  File "/opt/netbox-3.1.1/venv/lib/python3.8/site-packages/netbox_dns/urls.py", line 5, in <module>
    from .views import (
  File "/opt/netbox-3.1.1/venv/lib/python3.8/site-packages/netbox_dns/views.py", line 3, in <module>
    from netbox_dns.forms import (
  File "/opt/netbox-3.1.1/venv/lib/python3.8/site-packages/netbox_dns/forms.py", line 37, in <module>
    class ZoneForm(BootstrapMixin, CustomFieldModelForm):
  File "/opt/netbox-3.1.1/venv/lib/python3.8/site-packages/django/forms/models.py", line 226, in __new__
    new_class = super().__new__(mcs, name, bases, attrs)
  File "/opt/netbox-3.1.1/venv/lib/python3.8/site-packages/django/forms/forms.py", line 31, in __new__
    new_class = super().__new__(mcs, name, bases, attrs)
  File "/opt/netbox-3.1.1/venv/lib/python3.8/site-packages/django/forms/widgets.py", line 191, in __new__
    new_class = super().__new__(mcs, name, bases, attrs)
TypeError: Cannot create a consistent method resolution
order (MRO) for bases BootstrapMixin, CustomFieldModelForm

A test suite for the automatic PTR generation feature is missing

Generating the PTR records for A/AAAA records automatically is a critical feature for DNS operation and must work reliably, so specific tests are required to ensure the mechanism doesn't break, especially with later updates to the plugin. So a suite of unit tests should be provided.

Show associated zones at NameServers view.

It would be nice to see which zones are associated with the name server at the Name Servers view.
Also, to associate a Name Server to devices and VMs. Or even with services already described on device/VM, so we know where it is and in which IP address it responds.

Define SOA records by their elements

Another sensible addition would affect the issue of SOA records.

There needs to be exactly one SOA record per zone, and their contents is structured:

  • MNAME (primary name server)
  • RNAME (admin email in dotted format, i.e. with . instead of @)
  • SERIAL (the incrementing serial number of the zone data)
  • REFRESH (the refresh interval in which name servers must refresh zone data)
  • RETRY (the retry interval a name server should wait for until re-issuing a failed query)
  • EXPIRE (the timeout after which secondaries shoud age out zone data)
  • MINIMUM (the minimum TTL to use for negative responses such as NXDOMAIN)

IMHO it would make sense to make the entry of these data mandatory when creating a zone (apart from "SERIAL", which I'll cover later), use separate input fields for them and validate the data put into them, so that the maintenance of the field would be simplified.
[edit: Actually the alternative forms such as "1w" are not in the RFC, so we can limit this to entries in seconds to make life simpler for a start]

For the SERIAL field, multiple ways of handling them would be reasonable: If netbox-dns would be used as the primary source of the zone data it would make sense to generate them using a monotonously increasing serial number along one of the usual schemes such as yyyymmddxx or seconds since the epoch.

Define default TTL for RRs

Another enhancement suggestion:

It would be helpful to be able to define a default TTL per zone in the zone definitions, so that all records defined in that zone will default to that TTL (but be overrideable).

Fix detection of the proper view name in templates

In some list views (e.g. "Records"), when more than one item is selected the "Edit All" and "Delete All" buttons don't show up even if all permissions have been granted and the "Select all ... items" check box is checked.

The problem turns out to be the consequence of using the "validated_viewname" template tag instead of "plugin_validated_viewname". This was also the real cause of #87, fixed by simply hard-coding the view names (which is OK with model-specific templates, but not in general).

SOA MNAME can't be bulk-edited for zones

Obviously an oversight by myself: When multiple zones are selected, it is not possible to edit the SOA MNAME (primary name server) field for all of them because the related field is missing from the form.

Oops.

Migrate the list of zones using a nameserver to django_tables2

The zone table in the nameserver detail view is the only table still not using django_tables2. Unfortunately I messed this up myself in PR #43.

The table should be using the standard rendering library so that features like quick search and column configuration work.

Filter Records by Zone

While working with the Ansible lookup plugin for Netbox, I found that it's not possible to filter records by the zone they are belonging to. While not strictly necessary it is, especially when there are lots of records in the database, desirable to restrict the list of records retrieved from Netbox so the amount of data stays manageable.

When the API is used to build zone files, the canonical way of doing that would be to loop over all zones and then retrieve all records per zone to populate the zone file.

Quick search does not work

Trying to use the "Quick search" box in the Records list, but nothing happens.
Actually, I don't see any REST request sent, nor Javascript errors in the browser console (Chrome).

Issues with lists of immutable objects after upgrading to the new plugin interface

Branch netbox32-changes

I know @jeremystretch already mentioned that in his PR #128, but since that one is closed I would rather raise a separate issue so it's not forgotten.

As there is currently no supported way to inhibit the edit/delete buttons for objects that can't be edited or deleted, some strange behaviour is taking place in the "Managed Records" list views.

  • In the "Allen wrench"-submenu on the right side of the table, the Options "Edit" and "Delete" are displayed. However, actually using them leads to an error message that might be really misleading:
/plugins/netbox-dns/records/27/edit/
The requested page does not exist.

or, for "Delete":

 /plugins/netbox-dns/records/27/delete/
The requested page does not exist. 
  • As mentioned by Jeremy, the "Edit" and "Delete" buttons are displayed at the bottom of the table
  • The checkboxes for selecting items for editing or deletion are displayed although they shouldn't be
  • The checkboxes for selecting items for editing or deletion are displayed right left to the "Allen wrench" submenu instead of at the beginning of each row
  • Selecting items and then clicking on the "Edit" or "Delete" button results in a warning "No items were selected" (which is definitely untrue, although better than actually trying to edit/delete)

I expect all of these issues to go away as soon as there is a mechanism that allows to disable the edit/delete functionality in object lists.

Make sure the SOA_MNAME and SOA_RNAME entries in the SOA record end with a dot

I just realised that the SOA_MNAME and SOA_RNAME entries in the generated SOA record need to end with a dot, otherwise the name server will append the current origin to them, which is obviously wrong.

Currently they end with a dot when the NS name/SOA_MNAME data is added with a dot, otherwise it will incorrectly not have a dot at the end. This should be fixed.

Test data are semantically incorrect for some of the tests

While investigating #36, I initially thought that tests might keep failing because of an issue with the test data and my new validation code from PR #35. Specifically, "[00:00]" is not a valid IPv6 address, and "value 2" also does not parse as an IPv4 address in all likelihood.

Unfortunately this was not the reason for the failing tests after all, but whatever ... PR follows shortly.

Migration fails with new Netbox version 3.1.0

It seems either the new Netbox version 3.1.0 or one of its prerequisites is incompatible with Netbox DNS.

When trying to run manage.py makemigrations I get a long dump:

(netbox) [root@dns netbox]# /opt/netbox/netbox/manage.py makemigrations 
Traceback (most recent call last):
  File "/opt/netbox/netbox/manage.py", line 10, in <module>
    execute_from_command_line(sys.argv)
  File "/opt/netbox/lib/python3.8/site-packages/django/core/management/__init__.py", line 419, in execute_from_command_line
    utility.execute()
  File "/opt/netbox/lib/python3.8/site-packages/django/core/management/__init__.py", line 413, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/opt/netbox/lib/python3.8/site-packages/django/core/management/base.py", line 354, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/opt/netbox/lib/python3.8/site-packages/django/core/management/base.py", line 393, in execute
    self.check()
  File "/opt/netbox/lib/python3.8/site-packages/django/core/management/base.py", line 419, in check
    all_issues = checks.run_checks(
  File "/opt/netbox/lib/python3.8/site-packages/django/core/checks/registry.py", line 76, in run_checks
    new_errors = check(app_configs=app_configs, databases=databases)
  File "/opt/netbox/lib/python3.8/site-packages/django/core/checks/urls.py", line 13, in check_url_config
    return check_resolver(resolver)
  File "/opt/netbox/lib/python3.8/site-packages/django/core/checks/urls.py", line 23, in check_resolver
    return check_method()
  File "/opt/netbox/lib/python3.8/site-packages/django/urls/resolvers.py", line 412, in check
    for pattern in self.url_patterns:
  File "/opt/netbox/lib/python3.8/site-packages/django/utils/functional.py", line 48, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/opt/netbox/lib/python3.8/site-packages/django/urls/resolvers.py", line 598, in url_patterns
    patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
  File "/opt/netbox/lib/python3.8/site-packages/django/utils/functional.py", line 48, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/opt/netbox/lib/python3.8/site-packages/django/urls/resolvers.py", line 591, in urlconf_module
    return import_module(self.urlconf_name)
  File "/opt/netbox/lib64/python3.8/importlib/__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1014, in _gcd_import
  File "<frozen importlib._bootstrap>", line 991, in _find_and_load
  File "<frozen importlib._bootstrap>", line 975, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 671, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 783, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "/opt/netbox/netbox/netbox/urls.py", line 9, in <module>
    from extras.plugins.urls import plugin_admin_patterns, plugin_patterns, plugin_api_patterns
  File "/opt/netbox/netbox/extras/plugins/urls.py", line 28, in <module>
    urlpatterns = import_object(f"{plugin_path}.urls.urlpatterns")
  File "/opt/netbox/netbox/extras/plugins/utils.py", line 31, in import_object
    spec.loader.exec_module(module)
  File "/opt/netbox/lib/python3.8/site-packages/netbox_dns/urls.py", line 5, in <module>
    from .views import (
  File "/opt/netbox/lib/python3.8/site-packages/netbox_dns/views.py", line 3, in <module>
    from netbox_dns.forms import (
  File "/opt/netbox/lib/python3.8/site-packages/netbox_dns/forms.py", line 37, in <module>
    class ZoneForm(BootstrapMixin, CustomFieldModelForm):
  File "/opt/netbox/lib/python3.8/site-packages/django/forms/models.py", line 226, in __new__
    new_class = super().__new__(mcs, name, bases, attrs)
  File "/opt/netbox/lib/python3.8/site-packages/django/forms/forms.py", line 31, in __new__
    new_class = super().__new__(mcs, name, bases, attrs)
  File "/opt/netbox/lib/python3.8/site-packages/django/forms/widgets.py", line 191, in __new__
    new_class = super().__new__(mcs, name, bases, attrs)
TypeError: Cannot create a consistent method resolution
order (MRO) for bases BootstrapMixin, CustomFieldModelForm

NetBox 3.2 Beta 2: Some classes have been renamed/replaced

Some classes in Beta 2 are different from Beta 1 (new class names, some new functionality):

NetBoxModelSerializer replaces PrimaryModelSerializer
NetBoxModelViewSet replaces ModelViewSet
NetBoxRouter replaces OrderedDefaultRouter

The code needs to be adjusted accordingly.

Adding or renaming a reverse zone with many A/AAAA records in the databae is slow

Zones with names ending on in-addr.arpa or ip6.arpa get some special handing because in most cases they contain automatically generated PTR records for A and AAAA records. In most cases that is not an issue as only records within that zone are affected, but there is a case that has some potential for improvement.

If A reverse zone is created or renamed, that special handling consists in finding out which A or AAAA records in the system have values that need to be inserted in the new reverse zone, or migrated from other reverse zones they are currently in (this is the case when a PTR was residing e.g. in zone y.z.in-addr.arpaand now a new zone x.y.z.in-addr.arpa gets created or renamed to from a different name where the record now belongs).

Currently, the process of finding out which address records are to be considered for having their PTR record added to the new or renamed zone is involving looking at all address records that don't have PTR generation disabled. This works, but when there are a lot of A/AAAA records in Netbox DNS it is getting slow, also because the process of finding a matching reverse zone is not completely trivial. If there are a couple of thousand A/AAAA records to consider, the fact that processing time increases linearly with the number of records in the database leads to inacceptable performance.

Automatic creation of the SOA Serial number

As outlined in discussion #64, there should be an option to create the SOA Serial number automatically on zone updates.

Every time a change to a zone is made (either to the zone itself, e.g. the SOA record of the zone, or to its records) the serial number in the SOA SERIAL field needs to be updated in order for DNS secondary servers to pick up the change and perform an IXFR/AXFR from their master.

Especially when PTR records are generated automatically, keeping track of which serial numbers need to be increased can be difficult because there may be multiple IPv4 and/or IPv6 PTR zones might me affected by changed A/AAAA records in one zone.

The proposed enhancement should take care of which zones have changed and only advance the serial numbers of zones that actually have changes, lest an unnecessary load might be put on the DNS infrastructure.

Allow the same zones within different "views"

We use external and internal views in BIND for the same zones, as many other people do.

For example, when we are inside the LAN, a host record like 'host1.example.com` points to a some local IP like 192.168.1.1.
The same record 'host1.example.com' when it get queried from external network, points to some real external IP like 195.XXX.XXX.XXX

https://www.cyberciti.biz/faq/linux-unix-bind9-named-configure-views/

Please allow the same zones but with different "view" types or something like that.

Tests failing in current main branch

While testing the changes for PR #35, I noticed that some of the tests for netbox_dns fail:

(netbox) [root@dns netbox-dns]# /opt/netbox/netbox/manage.py test netbox_dns
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
......................................F....F......................F....F......................F....F....
======================================================================
FAIL: test_get_object_anonymous (netbox_dns.tests.test_views.NameServerTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/opt/netbox/lib/python3.8/site-packages/django/test/utils.py", line 387, in inner
    return func(*args, **kwargs)
  File "/opt/netbox/netbox/utilities/testing/views.py", line 62, in test_get_object_anonymous
    self.assertHttpStatus(response, 200)
  File "/opt/netbox/netbox/utilities/testing/base.py", line 68, in assertHttpStatus
    self.assertEqual(response.status_code, expected_status, err_message)
AssertionError: 302 != 200 : Expected HTTP status 200; received 302: No data

======================================================================
FAIL: test_list_objects_anonymous (netbox_dns.tests.test_views.NameServerTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/opt/netbox/lib/python3.8/site-packages/django/test/utils.py", line 387, in inner
    return func(*args, **kwargs)
  File "/opt/netbox/netbox/utilities/testing/views.py", line 401, in test_list_objects_anonymous
    self.assertHttpStatus(response, 200)
  File "/opt/netbox/netbox/utilities/testing/base.py", line 68, in assertHttpStatus
    self.assertEqual(response.status_code, expected_status, err_message)
AssertionError: 302 != 200 : Expected HTTP status 200; received 302: No data

======================================================================
FAIL: test_get_object_anonymous (netbox_dns.tests.test_views.RecordTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/opt/netbox/lib/python3.8/site-packages/django/test/utils.py", line 387, in inner
    return func(*args, **kwargs)
  File "/opt/netbox/netbox/utilities/testing/views.py", line 62, in test_get_object_anonymous
    self.assertHttpStatus(response, 200)
  File "/opt/netbox/netbox/utilities/testing/base.py", line 68, in assertHttpStatus
    self.assertEqual(response.status_code, expected_status, err_message)
AssertionError: 302 != 200 : Expected HTTP status 200; received 302: No data

======================================================================
FAIL: test_list_objects_anonymous (netbox_dns.tests.test_views.RecordTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/opt/netbox/lib/python3.8/site-packages/django/test/utils.py", line 387, in inner
    return func(*args, **kwargs)
  File "/opt/netbox/netbox/utilities/testing/views.py", line 401, in test_list_objects_anonymous
    self.assertHttpStatus(response, 200)
  File "/opt/netbox/netbox/utilities/testing/base.py", line 68, in assertHttpStatus
    self.assertEqual(response.status_code, expected_status, err_message)
AssertionError: 302 != 200 : Expected HTTP status 200; received 302: No data

======================================================================
FAIL: test_get_object_anonymous (netbox_dns.tests.test_views.ZoneTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/opt/netbox/lib/python3.8/site-packages/django/test/utils.py", line 387, in inner
    return func(*args, **kwargs)
  File "/opt/netbox/netbox/utilities/testing/views.py", line 62, in test_get_object_anonymous
    self.assertHttpStatus(response, 200)
  File "/opt/netbox/netbox/utilities/testing/base.py", line 68, in assertHttpStatus
    self.assertEqual(response.status_code, expected_status, err_message)
AssertionError: 302 != 200 : Expected HTTP status 200; received 302: No data

======================================================================
FAIL: test_list_objects_anonymous (netbox_dns.tests.test_views.ZoneTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/opt/netbox/lib/python3.8/site-packages/django/test/utils.py", line 387, in inner
    return func(*args, **kwargs)
  File "/opt/netbox/netbox/utilities/testing/views.py", line 401, in test_list_objects_anonymous
    self.assertHttpStatus(response, 200)
  File "/opt/netbox/netbox/utilities/testing/base.py", line 68, in assertHttpStatus
    self.assertEqual(response.status_code, expected_status, err_message)
AssertionError: 302 != 200 : Expected HTTP status 200; received 302: No data

----------------------------------------------------------------------
Ran 104 tests in 5.102s

FAILED (failures=6)
Destroying test database for alias 'default'...

Unfortunately, it took me a while to find out that this was not due to my changes, but the tests also fail for the current main branch in exactly the same way.

This seems to be because the Netbox ViewTestCases "GetObjectViewTestCase" and "ListObjectsViewTestCase" fail for anonymous access, possibly because the views return an HTTP response code 302 instead of 200 in this case. I haven't dug any deeper yet, but will investigate when I find the time.

zone files

Would import export (bind) zone files be an option in the future ?

Also, now it could be cool to have an deploy button which uses netbox source to deploy DNS records to bind servers :-)

Just saying and wishing.

So far thanks for this great work

TableControls Error on Netbox v3.1.2

Hiya there,

I've had some issues accessing all web pages in Netbox, due to an error regarding inc/table_controls.html not existing.

I can successfully load pages such as 'zones' and 'nameservers' when copying to inc/table_controls.html via

cd /opt/netbox/netbox/templates/inc; cp table_controls_htmx.html table_controls.html

So it seems this plugin should reference table_controls_htmx.html, rather then table_controls.html

Automatically generate NS records for name servers

It would be a useful feature to maintain the NS records for the name servers defined for a zone automatically. Details are in the discussion I opened in #63.

When a name server is defined for a zone and the zone the name server is located in is within the data maintained in NetBox DNS, it should be verified that there actually is an address record in the zone the name server belongs to. External name servers can't be checked, so there should be no warning for them.

As the resolution of a name server's name is depending on which view a zone belongs to, this needs to be checked on zone level, not on the name server level.

API and GUI search for "name" and "value" fields should require exact matching

As pointed out by @jeroenvermeulen, matches for the name field in the API shoule be exact, not partial, so that it's possible to search for an exact record.

Furthermore, API and GUI filters for all name and value fields for records as well as names for name servers and zones should be exact as well. For case insensitive/partial searches, the filters can be modified in the API, and the "search" field can be used in the GUI, so no functionality is lost by changing that.

Link DNS RRs to IPAM data

This is probably more a long-term project than something that can be implemented in a singe PR.

In the IPAM module there are lots of IP address data, together with an optional DNS name. This is exactly the information that is maintained in the DNS module as well with a different focus. It would be very useful to provide some kind of link between the two in some way that probably needs to be discussed further.

Some ideas:

  • Make it possible to select the DNS hostname in IPAM from the data in the DNS zones
  • Provide links to IP Addresses (IPAM) to DNS names (DNS) and vice versa, potentially with some kind of referential integrity (when the IPAM address is removed, offer to remove the DNS name as well)
  • Create the DNS record for an IP Address when the "DNS name" field is filled in

I did not dig into the Netbox code base too deeply yet, so I'm not sure whether a plugin can change the behaviour of a core module (which would be necessary for some of the functionality sketched above), or if a cross-referece to data from a core module is possible at all from a plugin, but it would be really nice to have.

Another issue is that IP addresses are not necessarily in a 1-1 relation to DNS records if different VRFs or different DNS views (BIND jargon) are in use, so that one IPAM IP address might be present in different zones/views. This is something that probably needs some discussion.

soa-mname incorrectly typed as integer

Hiya there,

Currently I'm writing a python script to interpolate between the PowerDNS API and the Netbox API, while troubleshooting some API call issues, looking at the Netbox API documentation, adding zones via an API call via POST specifies the following

soa_mname 
integer
title: SOA MName

The MNAME should be a string, not an integer, as per the MNAME listed in https://www.cloudflare.com/en-gb/learning/dns/dns-records/dns-soa-record/

There would be no circumstances an SOA MNAME contained within the rrset returned would ever be an integer, so this type should be changed.

Create reverse zones from forward zone data

One really challenging issue with maintaining zone data is to keep the reverse resolution zones in-addr.arpa. and ip6.arpa. consistent with the forward zones.

In one of the DNS environments I maintain I do this using Ansible with a YAML file defining the zone data, some simple playbooks, a custom Ansible module and some Jinja 2-Templates creating the forward and reverse zones for IPv4 and IPv6, respectively, from that single source of data. Provided that the DNS module has all the zone data, it should be possible to create the reverse zones from the existing zone data internally as well.

There are some special cases which I managed using flags for the entries in the YAML file, and which would similarly be required for the automatic zone generation, specifically two booleans that tell the converter not to create IPv4 and/or IPv6 PTR records for a specific address, but in general the generation of the PTR records can be automated quite easily.

An implementation idea would be to create the reverse zones manually in the DNS plugin, providing a "Automatic Provisioning" flag that tells the plugin to automatically generate PTR records from A/AAAA records in the forward zones (of the same view, once that feature is implemented). The option to add some other records manually (i.e. for host names not in one of the locally administered zones) is necessary as well.

Validate address data entered for RRs

Currently it is possible to enter malformed data i.e. in the A and AAAA fields.

Using Python's ipaddr module it should be easy to detect and reject "IP addresses" like "192.168.1.300" or "this.is.not.an.ip.address", which are not allowed for address records. For other records such as TXT, CNAME it's not that simple, but in some cases validation should be possible as well (such as CNAME, which should be a valid name and occur only once).

SRV record type

First of all, thank you for this plugin!!
I have been looking for a way to document various DNS records, trying to desparately avoid using a spreadsheet, and keeping it together with NetBox is perfect.

Would it be possible to add support for SRV record type?

Thanks in advance.

Bulk edit: Switching A/AAAA records with conflicting adresses to disable_ptr=False causes exception

Steps to reproduce:

  1. Create a new zone zone1.example.com
  2. Create a new reverse zone 0.0.10.in-addr.arpa
  3. Import some records (example below) with identical IP addresses and disable_ptr=True
  4. The records can be created because they don't have an associated PTR record
  5. Now bulk edit the records and set disable_ptr to False

Example records:

zone,type,name,value,disable_ptr
zone1.example.com,A,clash1,10.0.0.10,true
zone1.example.com,A,clash2,10.0.0.10,true
zone1.example.com,A,clash3,10.0.0.10,true

Expected behaviour:

An error message is shown with the information that there were multiple A/AAAA records mapped to the same address with PTR enabled.

Observed behaviour:

<class 'django.db.utils.IntegrityError'>

duplicate key value violates unique constraint "unique_pointer_for_address"
DETAIL:  Key (type, value)=(A, 10.0.0.10) already exists.


Python version: 3.8.11
NetBox version: 3.2.0-beta1

Explanation:

Multiple A or AAAA records can point to the same IPv4 or IPv6 address, provided that there is either no PTR zone containing records pointing back from the address to the name, or all but at most one A/AAAA records have PTR generation disabled. The latter is the case when the above test data is imported (in a variation one could also set one of the "Disable PTR" values to False).

Setting all records' "Disable PTR" field to "False" should be caught earlier than when NetBox tries to insert the inconsistent data into the database, which is causing the exception.

Re-organise the code base

Working on the NetBox DNS code gets increasingly difficult because the files filters.py, forms.py etc. have grown in size over the last months, which makes them hard to maintain.

I suggest splitting them into smaller files wherever possible. Unfortunately, models.py still resists this approach because of the dependencies between the models, which would lead to the notirious circular import problem, but splitting the rest of the files is pretty straightforward.

Problem with pynetbox and the "netbox_dns" application label

Hi,

we have a problem.

I was just trying to use the Ansible Netbox plugin to fetch data from netbox_dns.

Apart from some pretty strange bugs in the Ansible plugin itself (which are not part of this problem), it uses the pynetbox Python module to access Netbox. And here's where the trouble starts.

When pynetbox creates an endpoint object to access Netbox, it rewrites the application name so that underscores are converted to dashes in the URL. So, to access, for example, nameservers, it constructs the API URL as follows: https://netbox.example.com/api/plugins/netbox-dns/nameservers/ which obviously will not work, as the real URL is https://netbox.example.com/api/plugins/netbox_dns/nameservers/.

This behaviour is hard-coded in pynetbox/core/endpoint.py:

    def __init__(self, api, app, name, model=None):
        self.return_obj = self._lookup_ret_obj(name, model)
        self.name = name.replace("_", "-")                                         <----
        self.api = api
        self.base_url = api.base_url
        self.token = api.token
        self.session_key = api.session_key
        self.url = "{base_url}/{app}/{endpoint}".format(
            base_url=self.base_url, app=app.name, endpoint=self.name,
        )
        self._choices = None

To really get rid of this it's probably necessary to change the URL schema so that it uses a dash instead of an underscore.

While not strictly forbidden, there are several recommendations around against using underscores in URLs (e.g. here, Caution: Google link), and this seems to be one of the occasions where it really bites.

disable_ptr field not available on Record CSV import

Another enhancement that I detected missing when I tried starting to actually work with the plugin.

When records are imported via CSV, the "disable_ptr" flag is not available as an importable field. It would however be really useful to be able to specify it in CSV.

NetBox version: 3.1.1 missing DB column

django.db.utils.ProgrammingError: column netbox_dns_zone.soa_serial_auto does not exist

<class 'django.db.utils.ProgrammingError'>

column netbox_dns_zone.soa_serial_auto does not exist
LINE 1: ...e"."soa_expire", "netbox_dns_zone"."soa_minimum", "netbox_dn...

Python version: 3.8.10
NetBox version: 3.1.1

Record Bulk Edit: No zones selectable

I found an interesting bug when I tested some of my new functionality. It is not possible to asssign zones with the RecordBulkEdit form.

Steps to reproduce

  • Install from scratch (I'm currently using the development branch, but it is reproducible with main as well)
  • Import some test name servers, zones and records, e.g.
name
ns1.example.com
ns2.example.com

name,status
zone1.example.com,active
zone2.example.com,active
zone3.example.com,active
zone4.example.com,active
zone5.example.com,active
zone6.example.com,active
zone7.example.com,active
zone8.example.com,active
zone9.example.com,active

zone,type,name,value
zone1.example.com,A,name1,10.0.1.1
zone1.example.com,A,name2,10.0.1.2
zone1.example.com,A,name3,10.0.1.3
zone1.example.com,A,name4,10.0.1.4
zone1.example.com,A,name5,10.0.1.5
zone1.example.com,A,name6,10.0.1.6
zone2.example.com,A,name1,10.0.2.1
zone2.example.com,A,name2,10.0.2.2
zone2.example.com,A,name3,10.0.2.3
zone2.example.com,A,name4,10.0.2.4
zone2.example.com,A,name5,10.0.2.5
zone2.example.com,A,name6,10.0.2.6
zone3.example.com,A,name1,10.0.3.1
zone3.example.com,A,name2,10.0.3.2
zone3.example.com,A,name3,10.0.3.3
zone3.example.com,A,name4,10.0.3.4
zone3.example.com,A,name5,10.0.3.5
zone3.example.com,A,name6,10.0.3.6
  • Go to the "Records" list in the side bar
  • Select a couple of records. It's not important how many you use
  • Scroll down and click on "Edit Selected"
  • Try to select a zone from the pull-down menu in the bulk edit screen.

Observed Result

The list of available zones is empty.

Expected Result

The list should contain the zones imported as test data.

Inhibit creation of incompatible record types in zones

Generally in a reverse zone there can't be any A/AAAA records and in a non-reverse zone there can't be any PTR records.

To improve the reliability of the system, creating records of the wrong type should be inhibited on the form and/or model level. Some other record types (e.g. MX) will also be affected by the same restrictions on PTR zones.

Missing zone migration

After new PRs merged I see there is a missing migration.

$ python3 manage.py makemigrations
Migrations for 'netbox_dns':
  /home/ausec/Dev/netbox-dns/netbox_dns/migrations/0007_alter_zone_soa_serial_auto.py
    - Alter field soa_serial_auto on zone

Here is the content of 0007_alter_zone_soa_serial_auto.py

# Generated by Django 3.2.9 on 2021-12-13 13:23

from django.db import migrations, models


class Migration(migrations.Migration):

    dependencies = [
        ('netbox_dns', '0006_zone_soa_serial_auto'),
    ]

    operations = [
        migrations.AlterField(
            model_name='zone',
            name='soa_serial_auto',
            field=models.BooleanField(default=True),
        ),
    ]

Investigating this issue I see that it might be related to PR #74.

Here are the added lines (135 - 139) to models.py in this PR

soa_serial_auto = models.BooleanField(
    verbose_name="Generate SOA Serial",
    help_text="Automatically generate the SOA Serial field",
    default=True,
)

Here is the result migration. Lines 14 - 18.

    ....
        operations = [
        migrations.AddField(
            model_name="zone",
            name="soa_serial_auto",
            field=models.BooleanField(default=False),
            preserve_default=False,
        ),
    ....

default "true" value not reflected in the migration file.

If I am missing something, please let me know

"view_helpers" still loaded in NetBox 3.2 compatibility branch

When testing the NetBox DNS plugin with NetBox 3.2 beta 1 I ran into an error clicking on "Change Log" in any of the list views.

(NetBox "feature" branch, NetBox DNS "netbox32-changes" branch)

'view_helpers' is not a registered tag library. Must be one of:
admin_list
admin_modify
admin_urls
builtins.filters
builtins.tags
buttons
cache
custom_links
django_rq
django_tables2
form_helpers
helpers
humanize
i18n
jquery_path
l10n
log
log_levels
mptt_admin
mptt_tags
navigation
perms
plugins
rest_framework
search
static
tz

NameServers cannot be added to new Zones or updated for existing zones using the API

During tests for issue #117 I found that some functionality is lacking in the API.

When a zone is created, it is not possible to add name servers to it by populating the "nameservers" field in the JSON data passed to the API. Instead of creating the nameservers, there is an error message that the standard serualizer's create() method cannot handle nested objects:

The `.create()` method does not support writable nested fields by default.

A similar issue pops up when trying to update the list of name servers using the API:

The `.update()` method does not support writable nested fields by default.

Both functionalities are needed for the API to be used in a sensible way to import data from other systems.

Error message in Zone Records/Managed Records view

When the number of records configured to be displayed per page is smaller than the number of records available in the zone view, switching to the "Records" tab causes an error:

Screenshot 2021-12-07 at 14 47 13

This can be worked around by modifying the number of displays, as it only occurs when more than one page is to be displayed according to the paginator settings.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.