Files
weave/plugin/ipam.go
T

90 lines
2.2 KiB
Go

package plugin
import (
"fmt"
"io/ioutil"
"net"
"net/http"
. "github.com/weaveworks/weave/common"
)
func (d *dockerer) ipamOp(ID string, op string) (*net.IPNet, error) {
weaveip, err := d.getContainerBridgeIP(WeaveContainer)
Log.Debugf("IPAM operation %s for %s", op, ID)
if err != nil {
return nil, err
}
var res *http.Response
url := fmt.Sprintf("http://%s:6784/ip/%s", weaveip, ipamID(ID))
Log.Debugf("Attempting to %s to %s", op, url)
if op == "POST" {
res, err = http.Post(url, "", nil)
} else if op == "GET" {
res, err = http.Get(url)
}
if err != nil {
return nil, err
}
if res.StatusCode != http.StatusOK {
return nil, fmt.Errorf("received status %d from IPAM", res.StatusCode)
}
body, err := ioutil.ReadAll(res.Body)
if err != nil {
return nil, err
}
return parseIP(string(body))
}
// returns an IP for the ID given, allocating a fresh one if necessary
func (d *dockerer) allocateIP(ID string) (*net.IPNet, error) {
return d.ipamOp(ID, "POST")
}
// returns an IP for the ID given, or nil if one has not been
// allocated
func (d *dockerer) lookupIP(ID string) (*net.IPNet, error) {
return d.ipamOp(ID, "GET")
}
// release an IP which is no longer needed
func (d *dockerer) releaseIP(ID string) error {
weaveip, err := d.getContainerBridgeIP(WeaveContainer)
if err != nil {
return err
}
req, err := http.NewRequest("DELETE", fmt.Sprintf("http://%s:6784/ip/%s", weaveip, ipamID(ID)), nil)
if err != nil {
return err
}
cl := &http.Client{}
res, err := cl.Do(req)
if err != nil {
return err
}
if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusNoContent {
return fmt.Errorf("unexpected HTTP status code from IP release: %d", res.StatusCode)
}
return nil
}
func parseIP(body string) (*net.IPNet, error) {
ip, ipnet, err := net.ParseCIDR(string(body))
if err != nil {
return nil, err
}
ipnet.IP = ip
return ipnet, nil
}
// If something looking like a container ID is supplied to IPAM, it
// will try to check that it's running, and return nothing (and empty
// string) if it's not. So I make sure it doesn't look like a
// container ID by including non-hex characters.
func ipamID(ID string) string {
return "endpoint:" + ID
}