Skip to content

Commit

Permalink
Merge pull request moby#525 from aboch/am
Browse files Browse the repository at this point in the history
IPAM driver
  • Loading branch information
mavenugo committed Oct 4, 2015
2 parents c3a9e0d + 763709c commit 0bf5afe
Show file tree
Hide file tree
Showing 44 changed files with 2,937 additions and 1,142 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ cmd/dnet/dnet
*.tmp
*.coverprofile

# IDE files
# IDE files and folders
.project
.settings/

libnetwork-build.created
19 changes: 17 additions & 2 deletions bitseq/sequence.go
Original file line number Diff line number Diff line change
Expand Up @@ -306,8 +306,23 @@ func (h *Handle) validateOrdinal(ordinal uint32) error {
}

// Destroy removes from the datastore the data belonging to this handle
func (h *Handle) Destroy() {
h.deleteFromStore()
func (h *Handle) Destroy() error {
for {
if err := h.deleteFromStore(); err != nil {
if _, ok := err.(types.RetryError); !ok {
return fmt.Errorf("internal failure while destroying the sequence: %v", err)
}
// Fetch latest
if err := h.store.GetObject(datastore.Key(h.Key()...), h); err != nil {
if err == datastore.ErrKeyNotFound { // already removed
return nil
}
return fmt.Errorf("failed to fetch from store when destroying the sequence: %v", err)
}
continue
}
return nil
}
}

// ToByteArray converts this handle's data into a byte array
Expand Down
44 changes: 38 additions & 6 deletions cmd/ovrouter/ovrouter.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/docker/libnetwork/driverapi"
"github.com/docker/libnetwork/drivers/overlay"
"github.com/docker/libnetwork/netlabel"
"github.com/docker/libnetwork/types"
"github.com/vishvananda/netlink"
)

Expand All @@ -18,7 +19,7 @@ type router struct {
}

type endpoint struct {
addr net.IPNet
addr *net.IPNet
mac net.HardwareAddr
name string
}
Expand All @@ -32,9 +33,40 @@ func (ep *endpoint) Interface() driverapi.InterfaceInfo {
return nil
}

func (ep *endpoint) AddInterface(mac net.HardwareAddr, ipv4 net.IPNet, ipv6 net.IPNet) error {
ep.addr = ipv4
ep.mac = mac
func (ep *endpoint) SetMacAddress(mac net.HardwareAddr) error {
if ep.mac != nil {
return types.ForbiddenErrorf("endpoint interface MAC address present (%s). Cannot be modified with %s.", ep.mac, mac)
}
if mac == nil {
return types.BadRequestErrorf("tried to set nil MAC address to endpoint interface")
}
ep.mac = types.GetMacCopy(mac)
return nil
}

func (ep *endpoint) SetIPAddress(address *net.IPNet) error {
if address.IP == nil {
return types.BadRequestErrorf("tried to set nil IP address to endpoint interface")
}
if address.IP.To4() == nil {
return types.NotImplementedErrorf("do not support ipv6 yet")
}
if ep.addr != nil {
return types.ForbiddenErrorf("endpoint interface IP present (%s). Cannot be modified with %s.", ep.addr, address)
}
ep.addr = types.GetIPNetCopy(address)
return nil
}

func (ep *endpoint) MacAddress() net.HardwareAddr {
return types.GetMacCopy(ep.mac)
}

func (ep *endpoint) Address() *net.IPNet {
return types.GetIPNetCopy(ep.addr)
}

func (ep *endpoint) AddressIPv6() *net.IPNet {
return nil
}

Expand Down Expand Up @@ -86,7 +118,7 @@ func main() {
}

if err := r.d.CreateNetwork("testnetwork",
map[string]interface{}{}); err != nil {
map[string]interface{}{}, nil, nil); err != nil {
fmt.Printf("Failed to create network in the driver: %v\n", err)
os.Exit(1)
}
Expand All @@ -111,7 +143,7 @@ func main() {
os.Exit(1)
}

ipAddr := &netlink.Addr{IPNet: &ep.addr, Label: ""}
ipAddr := &netlink.Addr{IPNet: ep.addr, Label: ""}
if err := netlink.AddrAdd(link, ipAddr); err != nil {
fmt.Printf("Failed to add address to the interface: %v\n", err)
os.Exit(1)
Expand Down
160 changes: 128 additions & 32 deletions controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ import (
"github.com/docker/libnetwork/datastore"
"github.com/docker/libnetwork/driverapi"
"github.com/docker/libnetwork/hostdiscovery"
"github.com/docker/libnetwork/ipamapi"
"github.com/docker/libnetwork/osl"
"github.com/docker/libnetwork/types"
)
Expand Down Expand Up @@ -116,7 +117,14 @@ type driverData struct {
capability driverapi.Capability
}

type ipamData struct {
driver ipamapi.Ipam
// default address spaces are provided by ipam driver at registration time
defaultLocalAddressSpace, defaultGlobalAddressSpace string
}

type driverTable map[string]*driverData
type ipamTable map[string]*ipamData
type networkTable map[string]*network
type endpointTable map[string]*endpoint
type sandboxTable map[string]*sandbox
Expand All @@ -125,6 +133,7 @@ type controller struct {
id string
networks networkTable
drivers driverTable
ipamDrivers ipamTable
sandboxes sandboxTable
cfg *config.Config
globalStore, localStore datastore.DataStore
Expand All @@ -145,11 +154,12 @@ func New(cfgOptions ...config.Option) (NetworkController, error) {
cfg.ProcessOptions(cfgOptions...)
}
c := &controller{
id: stringid.GenerateRandomID(),
cfg: cfg,
networks: networkTable{},
sandboxes: sandboxTable{},
drivers: driverTable{}}
id: stringid.GenerateRandomID(),
cfg: cfg,
networks: networkTable{},
sandboxes: sandboxTable{},
drivers: driverTable{},
ipamDrivers: ipamTable{}}
if err := initDrivers(c); err != nil {
return nil, err
}
Expand All @@ -160,13 +170,26 @@ func New(cfgOptions ...config.Option) (NetworkController, error) {
// But it cannot fail creating the Controller
log.Debugf("Failed to Initialize Datastore due to %v. Operating in non-clustered mode", err)
}
if err := c.initLocalStore(); err != nil {
log.Debugf("Failed to Initialize LocalDatastore due to %v.", err)
}
}

if err := initIpams(c, c.localStore, c.globalStore); err != nil {
return nil, err
}

if cfg != nil {
if err := c.restoreFromGlobalStore(); err != nil {
log.Debugf("Failed to restore from global Datastore due to %v", err)
}
if err := c.initDiscovery(cfg.Cluster.Watcher); err != nil {
// Failing to initalize discovery is a bad situation to be in.
// But it cannot fail creating the Controller
log.Debugf("Failed to Initialize Discovery : %v", err)
}
if err := c.initLocalStore(); err != nil {
log.Debugf("Failed to Initialize LocalDatastore due to %v.", err)
if err := c.restoreFromLocalStore(); err != nil {
log.Debugf("Failed to restore from local Datastore due to %v", err)
}
}

Expand Down Expand Up @@ -272,6 +295,30 @@ func (c *controller) RegisterDriver(networkType string, driver driverapi.Driver,
return nil
}

func (c *controller) RegisterIpamDriver(name string, driver ipamapi.Ipam) error {
if !config.IsValidName(name) {
return ErrInvalidName(name)
}

c.Lock()
_, ok := c.ipamDrivers[name]
c.Unlock()
if ok {
return driverapi.ErrActiveRegistration(name)
}
locAS, glbAS, err := driver.GetDefaultAddressSpaces()
if err != nil {
return fmt.Errorf("ipam driver %s failed to return default address spaces: %v", name, err)
}
c.Lock()
c.ipamDrivers[name] = &ipamData{driver: driver, defaultLocalAddressSpace: locAS, defaultGlobalAddressSpace: glbAS}
c.Unlock()

log.Debugf("Registering ipam provider: %s", name)

return nil
}

// NewNetwork creates a new network of the specified network type. The options
// are network specific and modeled in a generic way.
func (c *controller) NewNetwork(networkType, name string, options ...NetworkOption) (Network, error) {
Expand All @@ -292,6 +339,7 @@ func (c *controller) NewNetwork(networkType, name string, options ...NetworkOpti
network := &network{
name: name,
networkType: networkType,
ipamType: ipamapi.DefaultIPAM,
id: stringid.GenerateRandomID(),
ctrlr: c,
endpoints: endpointTable{},
Expand All @@ -300,14 +348,30 @@ func (c *controller) NewNetwork(networkType, name string, options ...NetworkOpti

network.processOptions(options...)

if err := c.addNetwork(network); err != nil {
if _, err := c.loadNetworkDriver(network); err != nil {
return nil, err
}

if err := c.updateToStore(network); err != nil {
cnfs, err := network.ipamAllocate()
if err != nil {
return nil, err
}
defer func() {
if err != nil {
for _, cn := range cnfs {
cn()
}
}
}()

if err = c.addNetwork(network); err != nil {
return nil, err
}

if err = c.updateToStore(network); err != nil {
log.Warnf("couldnt create network %s: %v", network.name, err)
if e := network.Delete(); e != nil {
log.Warnf("couldnt cleanup network %s: %v", network.name, err)
log.Warnf("couldnt cleanup network %s on network create failure (%v): %v", network.name, err, e)
}
return nil, err
}
Expand All @@ -316,29 +380,15 @@ func (c *controller) NewNetwork(networkType, name string, options ...NetworkOpti
}

func (c *controller) addNetwork(n *network) error {

c.Lock()
// Check if a driver for the specified network type is available
dd, ok := c.drivers[n.networkType]
c.Unlock()

if !ok {
var err error
dd, err = c.loadDriver(n.networkType)
if err != nil {
return err
}
if _, err := c.loadNetworkDriver(n); err != nil {
return err
}

n.Lock()
n.svcRecords = svcMap{}
n.driver = dd.driver
n.dataScope = dd.capability.DataScope
d := n.driver
n.Unlock()

// Create the network
if err := d.CreateNetwork(n.id, n.generic); err != nil {
if err := d.CreateNetwork(n.id, n.generic, n.getIPv4Data(), n.getIPv6Data()); err != nil {
return err
}
if n.isGlobalScoped() {
Expand Down Expand Up @@ -534,14 +584,39 @@ func (c *controller) loadDriver(networkType string) (*driverData, error) {
return dd, nil
}

func (c *controller) getDriver(networkType string) (*driverData, error) {
func (c *controller) loadIpamDriver(name string) (*ipamData, error) {
if _, err := plugins.Get(name, ipamapi.PluginEndpointType); err != nil {
if err == plugins.ErrNotFound {
return nil, types.NotFoundErrorf(err.Error())
}
return nil, err
}
c.Lock()
id, ok := c.ipamDrivers[name]
c.Unlock()
if !ok {
return nil, ErrInvalidNetworkDriver(name)
}
return id, nil
}

func (c *controller) getIPAM(name string) (id *ipamData, err error) {
var ok bool
c.Lock()
defer c.Unlock()
dd, ok := c.drivers[networkType]
id, ok = c.ipamDrivers[name]
c.Unlock()
if !ok {
return nil, types.NotFoundErrorf("driver %s not found", networkType)
id, err = c.loadIpamDriver(name)
}
return dd, nil
return id, err
}

func (c *controller) getIpamDriver(name string) (ipamapi.Ipam, error) {
id, err := c.getIPAM(name)
if err != nil {
return nil, err
}
return id.driver, nil
}

func (c *controller) Stop() {
Expand All @@ -551,3 +626,24 @@ func (c *controller) Stop() {
c.stopExternalKeyListener()
osl.GC()
}

func (c *controller) loadNetworkDriver(n *network) (driverapi.Driver, error) {
// Check if a driver for the specified network type is available
c.Lock()
dd, ok := c.drivers[n.networkType]
c.Unlock()
if !ok {
var err error
dd, err = c.loadDriver(n.networkType)
if err != nil {
return nil, err
}
}

n.Lock()
n.svcRecords = svcMap{}
n.driver = dd.driver
n.dataScope = dd.capability.DataScope
n.Unlock()
return dd.driver, nil
}
Loading

0 comments on commit 0bf5afe

Please sign in to comment.