Address order: sequential, reverse or random, per subnet and pool
- Which never-used pool address a new client gets: sequential (the lowest, as before), reverse or random, in the settings, a subnet or a single pool (FIRST-LAST:ORDER). When no never-used address is left, the one free the longest, whatever the order; returning clients keep theirs. - A subnet's pools are used in the order listed, or one at random weighted by its never-used addresses. Pools now keep the order they are given in (no more sorting by address). - CLI --address-order and --pool-order; --add-pool of an existing range changes its order in place. Web UI: per-pool order and a move-up button, pool and address order on the subnet and settings pages. - Kea's allocator: random is imported. Schema migration 5. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
29fc991ce1
commit
8ee430276c
29 files changed
+653
-79
No files matched your search
+28
-1
@@ -90,6 +90,9 @@ type importer struct {
|
||||
opts Options
|
||||
res *Result
|
||||
globals []string // interfaces-config interfaces
|
||||
// allocator is Dhcp4's allocator (iterative, random or flq).
|
||||
allocator string
|
||||
noted map[string]bool
|
||||
}
|
||||
|
||||
// ParseConfig reads a kea-dhcp4.conf.
|
||||
@@ -131,6 +134,17 @@ func jsonError(b []byte, err error) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// noteOnce adds a note once per key.
|
||||
func (im *importer) noteOnce(key, format string, args ...any) {
|
||||
if im.noted == nil {
|
||||
im.noted = map[string]bool{}
|
||||
}
|
||||
if !im.noted[key] {
|
||||
im.noted[key] = true
|
||||
im.note(format, args...)
|
||||
}
|
||||
}
|
||||
|
||||
func (im *importer) note(format string, args ...any) {
|
||||
im.res.Notes = append(im.res.Notes, fmt.Sprintf(format, args...))
|
||||
}
|
||||
@@ -154,7 +168,7 @@ func get[T any](o obj, key string, into *T) (bool, error) {
|
||||
// note.
|
||||
var (
|
||||
handledKeys = map[string]bool{"interfaces-config": true, "valid-lifetime": true, "option-data": true, "subnet4": true, "shared-networks": true,
|
||||
"reservations": true, "authoritative": true, "decline-probation-period": true}
|
||||
"reservations": true, "authoritative": true, "decline-probation-period": true, "allocator": true}
|
||||
ignoredKeys = map[string]string{
|
||||
"lease-database": "Steward keeps leases in its own database", "control-socket": "Steward has its own API",
|
||||
"loggers": "Steward logs to the journal", "renew-timer": "Steward sends half the lease time",
|
||||
@@ -195,6 +209,7 @@ func (im *importer) dhcp4(d obj) error {
|
||||
im.globals = append(im.globals, name)
|
||||
}
|
||||
}
|
||||
get(d, "allocator", &im.allocator)
|
||||
set := &im.res.State.Settings
|
||||
var vl int
|
||||
if ok, err := get(d, "valid-lifetime", &vl); err != nil {
|
||||
@@ -346,6 +361,18 @@ func (im *importer) subnet(s obj, shared obj) error {
|
||||
}
|
||||
sn.Options = so
|
||||
}
|
||||
alloc := im.allocator
|
||||
if shared != nil {
|
||||
get(shared, "allocator", &alloc)
|
||||
}
|
||||
get(s, "allocator", &alloc)
|
||||
switch alloc {
|
||||
case "random":
|
||||
// Kea picks among all the subnet's free addresses.
|
||||
sn.PoolOrder, sn.AddressOrder = model.PoolsRandom, model.OrderRandom
|
||||
case "flq":
|
||||
im.noteOnce("flq", "the allocator flq (free lease queue) became Steward's sequential order: a new client gets the lowest address never handed out, else the one free the longest")
|
||||
}
|
||||
if ok, _ := get(s, "interface", &iface); ok && iface == "" {
|
||||
iface = ""
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user