Documentation
¶
Overview ¶
Package ipam allocates the addresses of an om network on one node.
The allocation is node local, which is what makes it safe without a lock held across the cluster. A routed_bridge network gives every node a subnet of its own, so two nodes never draw from the same addresses. A bridge network gives every node the whole subnet, but its addresses are node local and not routable, so the same address on two nodes never meets.
Index ¶
- func Gateway(rng *net.IPNet) net.IP
- func Key(p naming.Path, rid string) string
- func PathOfKey(key string) (naming.Path, bool)
- func StoreDir(name string) string
- type Reservation
- type T
- func (t *T) Adopt(reservations []Reservation) (int, error)
- func (t *T) Allocate(key string) (net.IP, error)
- func (t *T) Allocated(key string) (net.IP, error)
- func (t *T) DrainPeers() (int, int, error)
- func (t *T) Free(key string) error
- func (t *T) Reap(exists func(key string) bool) (int, error)
- func (t *T) Reservations() ([]Reservation, error)
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Gateway ¶
Gateway returns the address the bridge of a range answers for, which is the first address of the range plus one.
Both network drivers derive the address of their bridge that way, from the range they hand out: the bridge driver from the whole subnet, the routed_bridge driver from the subnet of the node. So the allocator has one rule to keep and no second place for it to drift from.
func Key ¶
Key returns the reservation key of an ip resource.
An address belongs to a resource, not to an object: an instance holds as many ip resources as it needs, several of them in one network, and each has an address of its own. Keying on the object alone would have ip#0 and ip#1 draw the same one.
Types ¶
type Reservation ¶
Reservation is an address already held by a resource, which an adoption records so the resource keeps it.
type T ¶
type T struct {
// Name is the network the addresses are drawn from.
Name string
// Range is the addresses this node draws from.
Range *net.IPNet
// Gateway is not allocated: it is the address of the bridge.
Gateway net.IP
// Dir is where the reservations are recorded, one file per address.
Dir string
// PeerDirs are the reservation stores of the allocators sharing this
// range, read and never written. While ip.cni is still served by the
// host-local plugin, its store is one of these: an address it handed
// out has no reservation here, and would be handed out twice.
PeerDirs []string
// InUse reports the addresses the cluster says are taken. The daemon
// replicates the resource status of every instance, so this sees the
// addresses of objects whose reservation file this node cannot read.
//
// Neither network driver needs it: a routed_bridge gives this node a
// range no other node draws from, and the addresses of a bridge are
// node local and not routable. It is here for a network type that is
// neither.
InUse func() ([]net.IP, error)
}
T allocates in one network, on one node.
func (*T) Adopt ¶
func (t *T) Adopt(reservations []Reservation) (int, error)
Adopt records the addresses resources already hold, so the allocator hands out the addresses that are free rather than the addresses that have no reservation yet.
It is how the allocation of a network moves from an allocator that was keeping its own record. The record of the host-local plugin cannot serve: it names the holder of an address by the pid of a network namespace, which says nothing about which resource that is. The cluster status can, since it carries the object and the rid alongside the address.
An address already reserved is left alone, whoever holds it, so an adoption run twice changes nothing and an adoption run late does not take an address from the resource that drew it. The count returned is of the addresses this call recorded, which is how a setup says whether it had anything to adopt.
func (*T) Allocate ¶
Allocate returns the address reserved for key, reserving it when it has none.
The same key draws the same address as long as it stays free, so an object keeps its address across restarts and its name keeps meaning what it meant. The reservation is a file created exclusively, which is the whole of the locking: one node draws from this range, so there is no other writer.
func (*T) DrainPeers ¶
DrainPeers removes, from the stores of the allocators sharing this range, the record of every address this one now holds.
A store is read to know what an allocator om is replacing handed out. Once om reserves an address, that record says nothing om does not know, and leaving it makes the address unusable for as long as the file lasts: the allocator that wrote it does not run any more, so nothing else will ever remove it.
Only the addresses om holds are removed. An address in the store that om accounts for in no way is left, and stays excluded, because the reason it is there may be a resource whose status this node has not read.
func (*T) Free ¶
Free releases the address key holds, and does nothing when it holds none.
Only the holder frees an address: the file names who took it, and a reservation another key made is left alone.
func (*T) Reap ¶
Reap releases the reservations held for keys that no longer exist.
A resource releases its address when it stops, and a start that fails rolls the allocation back, so a reservation outliving its holder takes a crash at the wrong moment. It outlives it for good though: the key names an object that is gone, so nothing will ever come to release it, and the address is lost until someone reads the store and works out why.
A key is kept unless it is known not to exist. Anything else would race a resource that has just reserved an address and not yet finished starting.
func (*T) Reservations ¶
func (t *T) Reservations() ([]Reservation, error)
Reservations returns the addresses this allocator holds, with the key each is held for.
It reads the store rather than the cluster status, so an address shows up the moment it is reserved, before the object holding it has published a status saying so.