-
-
Notifications
You must be signed in to change notification settings - Fork 3
Introduce a new zone loader #15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
This will be used to monitor filesystem paths, for the zonefile loader as well as for Nameshed state.
This sets up 'LoaderState', currently without any automatic refresh mechanisms.
This provides a mid-level API similar to 'zonetree'. It has some important differences: - It does not support proper queries. - It uses 'domain::new'. - It can hold old versions of a zone. - It provides direct access to the SOA record. - It offers a synchronous API. The idea is to enhance it to store both unsigned and signed versions of a zone simultaneously, by separating the regular and signing-related records. This will provide a compact, uniform way to store zone data before and after signing.
- Also implement 'Debug' for 'ZoneContents'
This reimplements IXFR and AXFR based zone loading, strongly based on the existing implementation in the zone maintainer. The new code uses 'domain::new' wherever possible, and produces zone updates in the form of 'ZoneContents'. The interface should be changed in the future to improve performance by processing the zone changes in parallel and on dedicated threads (using 'tokio::task::spawn_blocking()'). This would be useful for coalescing IXFR diffs, computing diffs when an AXFR is received, and comparing zones if the user forces a reload. It's hard to tell what the performance impact of converting between the old-base and 'domain::new' is. It wouldn't be too hard to inline the XFR interpretation (which is especially easy for AXFRs), and that would eliminate most of the conversions.
This adds a simple zonefile loader based on 'new-zonefile'. It only returns an uncompressed zone, which needs to be compressed manually when integrated into 'ZoneContents'.
If a user is concerned that Nameshed's cache of loaded zone data is incorrect, reloading can be used to fetch a new version of the zone without relying on previous loaded zone data or to verify that the local copy of the latest version of the zone is correct. If ZONEMD is supported in the future, reloading could simply check the ZONEMD record against the local copy to verify correctness. Most of the time, Nameshed will be performing refreshes instead, which do trust the local copy and can perform more efficient incremental zone transfers.
Zones are refreshed periodically (as per the SOA REFRESH timer) and in response to source-specific events (e.g. NOTIFY messages and filesystem notifications). Because of its frequency, effort is taken to minimize the cost of a refresh, by avoiding work if the zone has not changed.
- Also use 'refresh' as the general term for 'refresh / reload'. The next step is to connect the new zone storage to the existing zonetree work so it is compatible with the rest of the codebase.
- Factor out old-new record conversions - Fix adding IXFR records to the right vec
The 'RefreshMonitor' is a transparent time scheduler. It can provide us with (an atomic snapshot of) the list of currently scheduled zone refreshes, which will be very useful for reporting Nameshed's state.
- The refresh/reload state logic (i.e. repeatedly locking the zone state and comparing the new data to what's there) has been unified between 'zonefile' and 'server'. - 'loader::refresh()' and 'reload()' now return mutex guards, so that the caller has better guarantees about state consistency across the function boundaries. - 'zone::loader::RefreshTimerState' has been implemented, which tracks the per-zone refresh timer state, and synchronizes it with the global 'RefreshMonitor' schedule. - When a zone reload/refresh occurs, the refresh timer is now updated accordingly, and a followup reload/refresh (if enqueued) is started.
This is pretty hacky, and there's plenty of work to go, but a local run seems to be working fine.
tertsdiepraam
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I might be dense, but I can't find where you remove the functionality you're replacing? Which of these files contains that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The rustfmt config change definitely doesn't make this easy to review.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Huh, I thought I had re-formatted the same code directly on main so it wouldn't show up in the diff.
| /// This is equal to `previous + soa.refresh`. If the SOA record | ||
| /// changes (e.g. due to a new version of the zone being loaded), this | ||
| /// is recomputed, and the refresh is rescheduled accordingly. | ||
| scheduled: Instant, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We talked about this in a huddle, but we should probably also store SystemTime or chrono::DateTime or something else serializable/displayable for the CLI.
src/lib.rs
Outdated
| //! Rotonda | ||
| #![allow(renamed_and_removed_lints)] | ||
| #![allow(clippy::unknown_clippy_lints)] | ||
| #![allow(clippy::uninlined_format_args)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Didn't we want fewer of these? ;p
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but these pop up in all the code unrelated to mine and make it harder for me to use Clippy. The right solution might be to fix all that code separately, but I think this particular lint represents a style choice and we may not want to enforce it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder why I'm not seeing them then? Are these still a problem?
Ah yeah, this PR supersedes all the zone maintainer code, and |
Further clear out old zone maintainer code.
|
Would it be in scope to fix #22 as part of this work? |
These were not being detected by older Rust versions.
It turns out Domain's XFR response interpretation code doesn't quite work as I expected, and returns 'None' in a case it should return a 'Some'. This can be worked around in the future, perhaps by manually traversing the XFR response.
We only reload files when the user requests it. Perhaps automatic tracking functionality would be useful for status commands, to inform the user there may be unsynchronized changes; but that's for later.
As part of the state management system, this will be fleshed out to save/load a TSIG secrets file.
- Implement a versioned serialization specification. - Implement top-level loading/saving commands for 'TsigStore'.
|
Note: We decided to prioritize other work first and come back to this later. |
This lays out a brand new zone loader, based on the existing zonemaintainer code. It builds in proper support for loading zonefiles, and uses new-base very prominently, but more importantly, demonstrates a new state management paradigm that I hope to use throughout Nameshed. It makes it much easier to examine and consistently snapshot the program's state. The difficulty is that I've never seen any other uses of this paradigm before, which means that I have to invent some things (e.g. scheduling events) from scratch. But I'm very confident in its reliability.
Tasks:
ZoneContentswrt signer-created zone versions@ximon18, I'd appreciate if you could test this out in your local sandbox. The new-base zone loader doesn't support quite as many record types yet, but I'm willing to address those now.