-
Notifications
You must be signed in to change notification settings - Fork 105
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
Lease storage API #111
Comments
@Natolumin this lease storage API seems like a really good idea, sorry to see that it didn't get more momentum! In a local build of CoreDHCP I experimented with using fsnotify to update the StaticRecords in the file plugin when something changed to the leases file. Would this be something worth polishing up and sending in as a PR, while this API is still a draft? |
This is definitely a draft - I have a somewhat working branch but we haven't managed to review either the design or the code yet and I haven't worked on it in a while either so it's not moving fast at all Certainly feel free to send your improvements - we will probably even be able to reuse them in this API if it ever goes forward |
Just wanted to make a note here that I read your design and it seems thoughtful. I had questions.
I also have a comment, which is that one of the things that appealed to me about coredhcp is that you don't impose any requirements on how expiration is supposed to work. In our use case as an ISP, we typically assign one address per interface. The subscriber is allowed to connect only one device at a time, so whatever device asks for an address/prefix on that interface we will give it the same address/prefix even if a different device just got that same lease 30 seconds ago. I don't think ours is a common use case but it's nice that it fits well here. |
Following #110 and #108 (comment) I want to start a discussion about what the lease storage API would/should look like. This is pretty long but I have no real conclusion at the end, I hope we can build feedback and some PoCs to see where we should go
Quick note about terminology:
consumer plugin
: Uses the interface to query/store leasesprovider plugin
: Implements the interface, stores and maintains lease informationBasics
The base interface should act like a map, indexed by a client ID, returning leases
What's a client ID ?
Probably not the same for v4 and v6.
v4 usually identifies client by hardware address, but there's also a client-identifier option (61) that probably almost nobody actually uses
v6 client-ID option is mandatory and is probably much safer to use
However even in v6 administrators often care more about the MAC addresses. Which the RFC forbids but that ship has sailed
What's a lease ?
There's an expiration date. That's easy (not)(We'll come back to this later)
There's an IP. Or multiple (v6, multiple IA_ADDR in a single IA_NA). Or a prefix (or multiple)
There can be multiple leases per client. This is extremely common in v6 but not nearly as much in v4
Can we need to search/index by other than a client ID ?
For things like ad-hoc replication, or leasequery, we may need a bulk read(/write) interface
Do we need additional data in addition ?
Information on the validity on the lease ? Eg if there is relay info, a
lease could be linked to a network segment, and if the client moves the
lease becomes invalid.
It might not need to be stored in the lease though
A solution could be to have optional auxiliary
interface{}
data. Howeverthis makes it harder to share a lease storage across several plugins (is
that something we want? need?). Maybe index the additional data by
plugin name/instance, and plugins can only retrieve leases they stored
themselves
Usage (and locking)
The most common operation of a consumer plugin is a read-modify-update loop on a single client:
This means we need to prevent another plugin (or the same plugin in another
request) from modifying leases for a client we've "looked up" and intend to update.
Interface
Looking up a client gives, along with the info, a token (opaque, managed by the plugin), which has to be given during updates to ensure consistency of the results.
On the backend this can map nicely to multiple constructs:
index, which is atomically compared when updating the value, and the
modification rejected if the base isn't the expected one
SELECT ... FOR UPDATE
(or equivalent),where the backend opens a transaction, and the token can be an
identifier/index to find the transaction later to complete it
provider plugin and have Lookup/Update take a lock and block instead
Notice that some of these operations, instead of actually "locking", return
an error on races at the time of the update.
Errors and retrying
Due to the diversity of backends, there are many cases where some calls can
fail in retryable ways. We'll need to define, along with the interface, error
types that have to be handled in a specific way by the clients.
We can define the base errors and providers will wrap them, and clients test with the go 1.13 error API if they match (
errors.Is
)At least:
token, retryable
(This doesn't preclude other errors, eg for bad parameters)
Lease Expiration
Leases expire, and something needs to clean them up at some point.
Either the lease storage plugin or the calling plugin has to clean up expired
leases. I'd rather the storage plugin handle it so that it doesn't need to be
reimplemented for multiple plugins. Additionally it will probably need some
specific knowledge of the backend to find/clean the leases
However, there may be additional handling to do on lease cleanup. At least if
there is IP allocation, IPs (may) need to be freed. I can think of 2 solutions:
(q: can we have multiple IPs in a single lease from multiple allocators ?
how do we handle that then)
pass the entire lease object ? How do you know which allocator to use to free it ?)
Anyway, First Draft
The text was updated successfully, but these errors were encountered: