Invert multicast option in plugin
Now it's off by default, and there is an option to enable the multicast route per-network. We turn it on for the `weave` network created when we start the plugin.
This commit is contained in:
1 parent
b1fa417381
commit
a1c3cba363
5 files changed
+125
-23
No files matched your search
+88
-12
@@ -2,9 +2,11 @@ package plugin
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"github.com/docker/libnetwork/drivers/remote/api"
|
||||
"github.com/docker/libnetwork/netlabel"
|
||||
"github.com/docker/libnetwork/types"
|
||||
|
||||
"github.com/vishvananda/netlink"
|
||||
@@ -15,18 +17,28 @@ import (
|
||||
"github.com/weaveworks/weave/plugin/skel"
|
||||
)
|
||||
|
||||
type driver struct {
|
||||
scope string
|
||||
noMulticastRoute bool
|
||||
sync.RWMutex
|
||||
endpoints map[string]struct{}
|
||||
const (
|
||||
MulticastOption = "works.weave.multicast"
|
||||
)
|
||||
|
||||
type network struct {
|
||||
hasMulticastRoute bool
|
||||
}
|
||||
|
||||
func New(client *docker.Client, weave *weaveapi.Client, scope string, noMulticastRoute bool) (skel.Driver, error) {
|
||||
type driver struct {
|
||||
scope string
|
||||
docker *docker.Client
|
||||
sync.RWMutex
|
||||
endpoints map[string]struct{}
|
||||
networks map[string]network
|
||||
}
|
||||
|
||||
func New(client *docker.Client, weave *weaveapi.Client, scope string) (skel.Driver, error) {
|
||||
driver := &driver{
|
||||
noMulticastRoute: noMulticastRoute,
|
||||
scope: scope,
|
||||
endpoints: make(map[string]struct{}),
|
||||
scope: scope,
|
||||
docker: client,
|
||||
endpoints: make(map[string]struct{}),
|
||||
networks: make(map[string]network),
|
||||
}
|
||||
|
||||
_, err := NewWatcher(client, weave, driver)
|
||||
@@ -49,11 +61,33 @@ func (driver *driver) GetCapabilities() (*api.GetCapabilityResponse, error) {
|
||||
|
||||
func (driver *driver) CreateNetwork(create *api.CreateNetworkRequest) error {
|
||||
driver.logReq("CreateNetwork", create, create.NetworkID)
|
||||
_, err := driver.setupNetworkInfo(create.NetworkID, stringOptions(create))
|
||||
return err
|
||||
}
|
||||
|
||||
// Deal with excessively-generic way the options get decoded from JSON
|
||||
func stringOptions(create *api.CreateNetworkRequest) map[string]string {
|
||||
if create.Options != nil {
|
||||
if data, found := create.Options[netlabel.GenericData]; found {
|
||||
if options, ok := data.(map[string]interface{}); ok {
|
||||
out := make(map[string]string, len(options))
|
||||
for key, value := range options {
|
||||
if str, ok := value.(string); ok {
|
||||
out[key] = str
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (driver *driver) DeleteNetwork(delete *api.DeleteNetworkRequest) error {
|
||||
driver.logReq("DeleteNetwork", delete, delete.NetworkID)
|
||||
func (driver *driver) DeleteNetwork(delreq *api.DeleteNetworkRequest) error {
|
||||
driver.logReq("DeleteNetwork", delreq, delreq.NetworkID)
|
||||
driver.Lock()
|
||||
delete(driver.networks, delreq.NetworkID)
|
||||
driver.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -96,6 +130,10 @@ func (driver *driver) EndpointInfo(req *api.EndpointInfoRequest) (*api.EndpointI
|
||||
func (driver *driver) JoinEndpoint(j *api.JoinRequest) (*api.JoinResponse, error) {
|
||||
driver.logReq("JoinEndpoint", j, fmt.Sprintf("%s:%s to %s", j.NetworkID, j.EndpointID, j.SandboxKey))
|
||||
|
||||
network, err := driver.findNetworkInfo(j.NetworkID)
|
||||
if err != nil {
|
||||
return nil, driver.error("JoinEndpoint", "unable to find network info: %s", err)
|
||||
}
|
||||
name, peerName := vethPair(j.EndpointID)
|
||||
if _, err := weavenet.CreateAndAttachVeth(name, peerName, weavenet.WeaveBridgeName, 0, nil); err != nil {
|
||||
return nil, driver.error("JoinEndpoint", "%s", err)
|
||||
@@ -107,7 +145,7 @@ func (driver *driver) JoinEndpoint(j *api.JoinRequest) (*api.JoinResponse, error
|
||||
DstPrefix: weavenet.VethName,
|
||||
},
|
||||
}
|
||||
if !driver.noMulticastRoute {
|
||||
if network.hasMulticastRoute {
|
||||
multicastRoute := api.StaticRoute{
|
||||
Destination: "224.0.0.0/4",
|
||||
RouteType: types.CONNECTED,
|
||||
@@ -118,6 +156,44 @@ func (driver *driver) JoinEndpoint(j *api.JoinRequest) (*api.JoinResponse, error
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (driver *driver) findNetworkInfo(id string) (network, error) {
|
||||
driver.Lock()
|
||||
network, found := driver.networks[id]
|
||||
driver.Unlock()
|
||||
if found {
|
||||
return network, nil
|
||||
}
|
||||
info, err := driver.docker.NetworkInfo(id)
|
||||
if err != nil {
|
||||
return network, err
|
||||
}
|
||||
return driver.setupNetworkInfo(id, info.Options)
|
||||
}
|
||||
|
||||
func (driver *driver) setupNetworkInfo(id string, options map[string]string) (network, error) {
|
||||
var network network
|
||||
for key, value := range options {
|
||||
switch key {
|
||||
case MulticastOption:
|
||||
if value == "" { // interpret "--opt works.weave.multicast" as "turn it on"
|
||||
network.hasMulticastRoute = true
|
||||
} else {
|
||||
var err error
|
||||
if network.hasMulticastRoute, err = strconv.ParseBool(value); err != nil {
|
||||
return network, fmt.Errorf("unrecognized value %q for option %s", value, key)
|
||||
}
|
||||
|
||||
}
|
||||
default:
|
||||
driver.warn("setupNetworkInfo", "unrecognized option: %s", key)
|
||||
}
|
||||
}
|
||||
driver.Lock()
|
||||
driver.networks[id] = network
|
||||
driver.Unlock()
|
||||
return network, nil
|
||||
}
|
||||
|
||||
func (driver *driver) LeaveEndpoint(leave *api.LeaveRequest) error {
|
||||
driver.logReq("LeaveEndpoint", leave, fmt.Sprintf("%s:%s", leave.NetworkID, leave.EndpointID))
|
||||
|
||||
|
||||
+10
-7
@@ -42,7 +42,7 @@ func main() {
|
||||
flag.StringVar(&logLevel, "log-level", "info", "logging level (debug, info, warning, error)")
|
||||
flag.StringVar(&address, "socket", "/run/docker/plugins/weave.sock", "socket on which to listen")
|
||||
flag.StringVar(&meshAddress, "meshsocket", "/run/docker/plugins/weavemesh.sock", "socket on which to listen in mesh mode")
|
||||
flag.BoolVar(&noMulticastRoute, "no-multicast-route", false, "do not add a multicast route to network endpoints")
|
||||
flag.BoolVar(&noMulticastRoute, "no-multicast-route", false, "deprecated (this is now the default)")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
@@ -73,18 +73,21 @@ func main() {
|
||||
}
|
||||
|
||||
Log.Println("Weave plugin", version, "Command line options:", os.Args[1:])
|
||||
if noMulticastRoute {
|
||||
Log.Warning("--no-multicast-route option has been removed; multicast is off by default")
|
||||
}
|
||||
Log.Info(dockerClient.Info())
|
||||
|
||||
err = run(dockerClient, weave, address, meshAddress, noMulticastRoute)
|
||||
err = run(dockerClient, weave, address, meshAddress)
|
||||
if err != nil {
|
||||
Log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func run(dockerClient *docker.Client, weave *weaveapi.Client, address, meshAddress string, noMulticastRoute bool) error {
|
||||
func run(dockerClient *docker.Client, weave *weaveapi.Client, address, meshAddress string) error {
|
||||
endChan := make(chan error, 1)
|
||||
if address != "" {
|
||||
globalListener, err := listenAndServe(dockerClient, weave, address, noMulticastRoute, endChan, "global", false)
|
||||
globalListener, err := listenAndServe(dockerClient, weave, address, endChan, "global", false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -92,7 +95,7 @@ func run(dockerClient *docker.Client, weave *weaveapi.Client, address, meshAddre
|
||||
defer globalListener.Close()
|
||||
}
|
||||
if meshAddress != "" {
|
||||
meshListener, err := listenAndServe(dockerClient, weave, meshAddress, noMulticastRoute, endChan, "local", true)
|
||||
meshListener, err := listenAndServe(dockerClient, weave, meshAddress, endChan, "local", true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -117,8 +120,8 @@ func run(dockerClient *docker.Client, weave *weaveapi.Client, address, meshAddre
|
||||
}
|
||||
}
|
||||
|
||||
func listenAndServe(dockerClient *docker.Client, weave *weaveapi.Client, address string, noMulticastRoute bool, endChan chan<- error, scope string, withIpam bool) (net.Listener, error) {
|
||||
d, err := netplugin.New(dockerClient, weave, scope, noMulticastRoute)
|
||||
func listenAndServe(dockerClient *docker.Client, weave *weaveapi.Client, address string, endChan chan<- error, scope string, withIpam bool) (net.Listener, error) {
|
||||
d, err := netplugin.New(dockerClient, weave, scope)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -4,7 +4,9 @@ package main
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/fsouza/go-dockerclient"
|
||||
docker "github.com/fsouza/go-dockerclient"
|
||||
|
||||
"github.com/weaveworks/weave/plugin/net"
|
||||
)
|
||||
|
||||
func createPluginNetwork(args []string) error {
|
||||
@@ -23,6 +25,7 @@ func createPluginNetwork(args []string) error {
|
||||
CheckDuplicate: true,
|
||||
Driver: driverName,
|
||||
IPAM: docker.IPAMOptions{Driver: driverName},
|
||||
Options: map[string]interface{}{plugin.MulticastOption: "true"},
|
||||
})
|
||||
if err != docker.ErrNetworkAlreadyExists && err != nil {
|
||||
// Despite appearances to the contrary, CreateNetwork does
|
||||
|
||||
@@ -26,6 +26,13 @@ store, but the first part of
|
||||
|
||||
>**Note:** In the case of multiple networks using the `weave` driver, all containers are on the same virtual network but Docker allocates their addresses on different subnets so they cannot talk to each other directly.
|
||||
|
||||
The plugin accepts the following options via `docker network create ... --opt`:
|
||||
|
||||
* `works.weave.multicast` -- tells weave to add a static IP
|
||||
route for multicast traffic onto its interface.
|
||||
|
||||
>**Note:** If you connect a container to multiple Weave networks, at
|
||||
most one of them can have the multicast route enabled.
|
||||
|
||||
**See Also**
|
||||
|
||||
|
||||
@@ -8,10 +8,13 @@ show_multicast_route_on() {
|
||||
|
||||
start_suite "--no-multicast-route operation"
|
||||
|
||||
# In case one is left around from a previous test
|
||||
$SSH $HOST1 docker network rm testmcasttrue testmcastfalse >/dev/null 2>&1 || true
|
||||
|
||||
# Ensure containers run either way have no multicast route
|
||||
weave_on $HOST1 launch-router
|
||||
weave_on $HOST1 launch-proxy --no-multicast-route
|
||||
weave_on $HOST1 launch-plugin --no-multicast-route
|
||||
weave_on $HOST1 launch-plugin # plugin defaults to multicast off except for 'net=weave'
|
||||
|
||||
start_container $HOST1 --no-multicast-route --name c1
|
||||
proxy_start_container $HOST1 --name c2
|
||||
@@ -19,7 +22,16 @@ start_container_local_plugin $HOST1 --name=c3
|
||||
|
||||
assert "show_multicast_route_on $HOST1 c1"
|
||||
assert "show_multicast_route_on $HOST1 c2"
|
||||
assert "show_multicast_route_on $HOST1 c3"
|
||||
assert "show_multicast_route_on $HOST1 c3" "224.0.0.0/4 dev ethwe0 "
|
||||
|
||||
# Now try via docker network options
|
||||
# using ssh rather than docker -H because CircleCI docker client is older
|
||||
$SSH $HOST1 docker network create --driver weavemesh --ipam-driver weavemesh --opt works.weave.multicast=false testmcastfalse
|
||||
$SSH $HOST1 docker run --net=testmcastfalse --name c4 -di $SMALL_IMAGE /bin/sh
|
||||
assert "show_multicast_route_on $HOST1 c4"
|
||||
$SSH $HOST1 docker network create --driver weavemesh --ipam-driver weavemesh --opt works.weave.multicast testmcasttrue
|
||||
$SSH $HOST1 docker run --net=testmcasttrue --name c5 -di $SMALL_IMAGE /bin/sh
|
||||
assert "show_multicast_route_on $HOST1 c5" "224.0.0.0/4 dev ethwe0 "
|
||||
|
||||
# Ensure current proxy options are obeyed on container start
|
||||
docker_on $HOST1 stop -t 1 c2
|
||||
@@ -30,6 +42,7 @@ proxy docker_on $HOST1 start c2
|
||||
|
||||
assert "show_multicast_route_on $HOST1 c2" "224.0.0.0/4 dev ethwe "
|
||||
|
||||
docker_on $HOST1 rm -f c3
|
||||
docker_on $HOST1 rm -f c3 c4 c5
|
||||
$SSH $HOST1 docker network rm testmcasttrue testmcastfalse
|
||||
|
||||
end_suite
|
||||
Reference in new issue
Block a user