GithubHelp home page GithubHelp logo

Comments (11)

peteeckel avatar peteeckel commented on August 16, 2024

This is correct and a result of the way Django works internally.

The nameservers relation is a ManyToManyField, and thus it is not populated when the zone itself is created. So technically when the zone create event is triggered there are no nameservers yet, they get added in a separate step (which is why you see them in a zone update event).

This has some implications in other places in the code as well, but normally you don't see them - except when you handle events. There is, for instance, the following code in models.py:

@receiver(m2m_changed, sender=Zone.nameservers.through)
def update_ns_records(**kwargs):
    if kwargs.get("action") not in ["post_add", "post_remove"]:
        return

    zone = kwargs.get("instance")
    zone.update_ns_records()

This is necessary to internally handle updates to the name servers of a zone, because the nameservers are not necessarily up to date when a zone is created or updated. To create the NS records for a zone, we need to wait for the m2m_changed event for the name servers field.

This is also explained in netbox-community/netbox#6284.

I'm not sure if there's a simple way to handle the issue, but I will look into it.

from netbox-dns.

peteeckel avatar peteeckel commented on August 16, 2024

I just had a closer look at it and created a webhook debug setup that triggers on zone creation and update. Then I created a zone and got in total three events: The create event and two update events.

[1] Sun, 14 May 2023 15:41:46 GMT 127.0.0.1 "POST / HTTP/1.1" 200 -
Host: localhost:9000
Accept-Encoding: identity
Content-Type: application/json
Content-Length: 1449
User-Agent: python-urllib3/1.26.15

{
    "event": "created",
    "timestamp": "2023-05-14 15:41:46.214018+00:00",
    "model": "zone",
    "username": "admin",
    "request_id": "bb74c9b4-72ee-49f3-b797-57c0c3263cfc",
    "data": {
        "id": 61,
        "url": "/api/plugins/netbox-dns/zones/61/",
        "name": "zone31.example.com",
        "view": {
            "id": 2,
            "url": "/api/plugins/netbox-dns/views/2/",
            "display": "external",
            "name": "external"
        },
        "display": "[external] zone31.example.com",
        "nameservers": [],
        "status": "active",
        "description": "",
        "tags": [],
        "created": "2023-05-14T15:41:46.055321Z",
        "last_updated": "2023-05-14T15:41:46.055479Z",
        "default_ttl": 86400,
        "soa_ttl": 86400,
        "soa_mname": {
            "id": 1,
            "url": "/api/plugins/netbox-dns/nameservers/1/",
            "display": "ns1.example.com",
            "name": "ns1.example.com"
        },
        "soa_rname": "hostmaster.example.com",
        "soa_serial": 1684078907,
        "soa_serial_auto": true,
        "soa_refresh": 172800,
        "soa_retry": 7200,
        "soa_expire": 2592000,
        "soa_minimum": 3600,
        "custom_fields": {}
    },
    "snapshots": {
        "prechange": null,
        "postchange": {
            "created": "2023-05-14T15:41:46.055Z",
            "last_updated": "2023-05-14T15:41:46.055Z",
            "view": 2,
            "name": "zone31.example.com",
            "status": "active",
            "default_ttl": 86400,
            "soa_ttl": 86400,
            "soa_mname": 1,
            "soa_rname": "hostmaster.example.com",
            "soa_serial": 1684078907,
            "soa_refresh": 172800,
            "soa_retry": 7200,
            "soa_expire": 2592000,
            "soa_minimum": 3600,
            "soa_serial_auto": true,
            "description": "",
            "arpa_network": null,
            "nameservers": [],
            "custom_fields": {},
            "tags": []
        }
    }
}
Completed request #1
------------
[2] Sun, 14 May 2023 15:41:46 GMT 127.0.0.1 "POST / HTTP/1.1" 200 -
Host: localhost:9000
Accept-Encoding: identity
Content-Type: application/json
Content-Length: 1685
User-Agent: python-urllib3/1.26.15

{
    "event": "updated",
    "timestamp": "2023-05-14 15:41:46.222865+00:00",
    "model": "zone",
    "username": "admin",
    "request_id": "bb74c9b4-72ee-49f3-b797-57c0c3263cfc",
    "data": {
        "id": 61,
        "url": "/api/plugins/netbox-dns/zones/61/",
        "name": "zone31.example.com",
        "view": {
            "id": 2,
            "url": "/api/plugins/netbox-dns/views/2/",
            "display": "external",
            "name": "external"
        },
        "display": "[external] zone31.example.com",
        "nameservers": [
            {
                "id": 2,
                "url": "/api/plugins/netbox-dns/nameservers/2/",
                "display": "ns2.example.com",
                "name": "ns2.example.com"
            },
            {
                "id": 3,
                "url": "/api/plugins/netbox-dns/nameservers/3/",
                "display": "ns3.example.com",
                "name": "ns3.example.com"
            }
        ],
        "status": "active",
        "description": "",
        "tags": [],
        "created": "2023-05-14T15:41:46.055321Z",
        "last_updated": "2023-05-14T15:41:46.140365Z",
        "default_ttl": 86400,
        "soa_ttl": 86400,
        "soa_mname": {
            "id": 1,
            "url": "/api/plugins/netbox-dns/nameservers/1/",
            "display": "ns1.example.com",
            "name": "ns1.example.com"
        },
        "soa_rname": "hostmaster.example.com",
        "soa_serial": 1684078907,
        "soa_serial_auto": true,
        "soa_refresh": 172800,
        "soa_retry": 7200,
        "soa_expire": 2592000,
        "soa_minimum": 3600,
        "custom_fields": {}
    },
    "snapshots": {
        "prechange": null,
        "postchange": {
            "created": "2023-05-14T15:41:46.055Z",
            "last_updated": "2023-05-14T15:41:46.140Z",
            "view": 2,
            "name": "zone31.example.com",
            "status": "active",
            "default_ttl": 86400,
            "soa_ttl": 86400,
            "soa_mname": 1,
            "soa_rname": "hostmaster.example.com",
            "soa_serial": 1684078907,
            "soa_refresh": 172800,
            "soa_retry": 7200,
            "soa_expire": 2592000,
            "soa_minimum": 3600,
            "soa_serial_auto": true,
            "description": "",
            "arpa_network": null,
            "nameservers": [
                2,
                3
            ],
            "custom_fields": {},
            "tags": []
        }
    }
}
Completed request #2
------------
[3] Sun, 14 May 2023 15:41:46 GMT 127.0.0.1 "POST / HTTP/1.1" 200 -
Host: localhost:9000
Accept-Encoding: identity
Content-Type: application/json
Content-Length: 1685
User-Agent: python-urllib3/1.26.15

{
    "event": "updated",
    "timestamp": "2023-05-14 15:41:46.223925+00:00",
    "model": "zone",
    "username": "admin",
    "request_id": "bb74c9b4-72ee-49f3-b797-57c0c3263cfc",
    "data": {
        "id": 61,
        "url": "/api/plugins/netbox-dns/zones/61/",
        "name": "zone31.example.com",
        "view": {
            "id": 2,
            "url": "/api/plugins/netbox-dns/views/2/",
            "display": "external",
            "name": "external"
        },
        "display": "[external] zone31.example.com",
        "nameservers": [
            {
                "id": 2,
                "url": "/api/plugins/netbox-dns/nameservers/2/",
                "display": "ns2.example.com",
                "name": "ns2.example.com"
            },
            {
                "id": 3,
                "url": "/api/plugins/netbox-dns/nameservers/3/",
                "display": "ns3.example.com",
                "name": "ns3.example.com"
            }
        ],
        "status": "active",
        "description": "",
        "tags": [],
        "created": "2023-05-14T15:41:46.055321Z",
        "last_updated": "2023-05-14T15:41:46.176236Z",
        "default_ttl": 86400,
        "soa_ttl": 86400,
        "soa_mname": {
            "id": 1,
            "url": "/api/plugins/netbox-dns/nameservers/1/",
            "display": "ns1.example.com",
            "name": "ns1.example.com"
        },
        "soa_rname": "hostmaster.example.com",
        "soa_serial": 1684078907,
        "soa_serial_auto": true,
        "soa_refresh": 172800,
        "soa_retry": 7200,
        "soa_expire": 2592000,
        "soa_minimum": 3600,
        "custom_fields": {}
    },
    "snapshots": {
        "prechange": null,
        "postchange": {
            "created": "2023-05-14T15:41:46.055Z",
            "last_updated": "2023-05-14T15:41:46.176Z",
            "view": 2,
            "name": "zone31.example.com",
            "status": "active",
            "default_ttl": 86400,
            "soa_ttl": 86400,
            "soa_mname": 1,
            "soa_rname": "hostmaster.example.com",
            "soa_serial": 1684078907,
            "soa_refresh": 172800,
            "soa_retry": 7200,
            "soa_expire": 2592000,
            "soa_minimum": 3600,
            "soa_serial_auto": true,
            "description": "",
            "arpa_network": null,
            "nameservers": [
                2,
                3
            ],
            "custom_fields": {},
            "tags": []
        }
    }
}
Completed request #3
------------

Because of the behaviour mentioned above, there will always be a zone update event for a new zone after the zone create event if the zone actually has name servers.

I also checked the events sent when objects are created with tags. Now it gets interesting: When I create a zone with a tag (but no nameserver), I get one event. When I do the same with an IPAM IP Address, I get one create event with the tags included. So there is a way to queue m2m updates properly. Let me see if we can jump on that train ... :-)

from netbox-dns.

kemeris2000 avatar kemeris2000 commented on August 16, 2024

I just had a closer look at it and created a webhook debug setup that triggers on zone creation and update. Then I created a zone and got in total three events: The create event and two update events.

Because of the behaviour mentioned above, there will always be a zone update event for a new zone after the zone create event if the zone actually has name servers.

I also checked the events sent when objects are created with tags. Now it gets interesting: When I create a zone with a tag (but no nameserver), I get one event. When I do the same with an IPAM IP Address, I get one create event with the tags included. So there is a way to queue m2m updates properly. Let me see if we can jump on that train ... :-)

I observe the following:

case: 1 nameserver 0 tags
result: create, update

case: 2 nameserver 0 tags
result: create, update, update

case: 1 nameserver 1 tags
result: create, update, update

case: 2 nameserver 1 tags
result: create, update, update, update

In last case events "create" and first "update" produce identical "last_updated" timestamp.

I guess at the moment of script execution on create event, database table "netbox_dns_zone_nameservers" is not populated yet?

from netbox-dns.

kemeris2000 avatar kemeris2000 commented on August 16, 2024

At the moment I see only one dirty solution to store zone "id" and "last_updated" values locally on disk on create event, and send zone to BIND on last update event if "id" matches, difference of "last_updated" is less 1 second or so and nameservers exist.

from netbox-dns.

peteeckel avatar peteeckel commented on August 16, 2024

I delved a bit deeper into this yesterday, and I found some information that I currently can't piece together properly. Concentrating on tags first, because that is something that applies to all models, I found that for some reason tags are included in the create event for View and NameServer, but not for Record and Zone.

That indicates that some of NetBox DNS' internal processing interferes with the way NetBox works around the m2m_changed problem. I'll debug that further as soon as I can, this is really interesting.

from netbox-dns.

peteeckel avatar peteeckel commented on August 16, 2024

At the moment I see only one dirty solution to store zone "id" and "last_updated" values locally on disk on create event, and send zone to BIND on last update event if "id" matches, difference of "last_updated" is less 1 second or so and nameservers exist.

This is very similar to the way NetBox implements the workaround ... they queue Webhooks and flush them once everything is done.

Considering my earlier advice not to flush every change to the name server database it's not that dirty at all, though I would really like to find the root cause of the incomplete create events.

from netbox-dns.

kemeris2000 avatar kemeris2000 commented on August 16, 2024

I will wait for results of your attempt.

from netbox-dns.

kemeris2000 avatar kemeris2000 commented on August 16, 2024

Hi peteeckel, any progress on this issue?

from netbox-dns.

peteeckel avatar peteeckel commented on August 16, 2024

Hi @kemeris2000, there are three ways to deal with this:

  1. Wait until I find the time to work on it in my spare time,
  2. Find the solution and open a PR,
  3. Ask for a consultancy quotation.

Have a nice weekend!

from netbox-dns.

peteeckel avatar peteeckel commented on August 16, 2024

Hi @kemeris2000, it does not look like this can be solved easily within NetBox DNS or even NetBox.

I ran some tests with custom signal listeners on post_save and m2m_changed events for Zone and Zone.nameservers.through, and the serialize_object() method on the zone object does not seem to have the nameservers array populated in either.

That means that the code within NetBox that triggers the Webhooks can't see them either, which explains why the Webhook data does not contain data for nameservers as well.

This might be an issue within NetBox (the serialize_object() method could be flawed in some way) or within Django (unlikely, but possible). I'm not sure what triggers the issue, but clearly something is not working as expected.

from netbox-dns.

kemeris2000 avatar kemeris2000 commented on August 16, 2024

Thank you peteeckel for you time and effort! I guess it's not worth to investigate further. At the moment I propose simple workaround for everyone else who is interested:
do not trigger any actions on create event and handle zone creation and modifications on update event. Netbox webhook condition filters out unneeded update events:

{
    "and": [
        {
            "attr": "nameservers",
            "negate": true,
            "value": null
        }
    ]
}

from netbox-dns.

Related Issues (20)

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.