Browse Source

Add network events.

Signed-off-by: David Calavera <david.calavera@gmail.com>
David Calavera 9 years ago
parent
commit
f15af1eff7

+ 1 - 0
api/server/router/network/backend.go

@@ -19,4 +19,5 @@ type Backend interface {
 	DisconnectContainerFromNetwork(containerName string,
 		network libnetwork.Network) error
 	NetworkControllerEnabled() bool
+	DeleteNetwork(name string) error
 }

+ 1 - 15
api/server/router/network/network_routes.go

@@ -148,21 +148,7 @@ func (n *networkRouter) postNetworkDisconnect(ctx context.Context, w http.Respon
 }
 
 func (n *networkRouter) deleteNetwork(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
-	if err := httputils.ParseForm(r); err != nil {
-		return err
-	}
-
-	nw, err := n.backend.FindNetwork(vars["id"])
-	if err != nil {
-		return err
-	}
-
-	if runconfig.IsPreDefinedNetwork(nw.Name()) {
-		return httputils.WriteJSON(w, http.StatusForbidden,
-			fmt.Sprintf("%s is a pre-defined network and cannot be removed", nw.Name()))
-	}
-
-	return nw.Delete()
+	return n.backend.DeleteNetwork(vars["id"])
 }
 
 func buildNetworkResource(nw libnetwork.Network) *types.NetworkResource {

+ 8 - 3
daemon/container_operations_unix.go

@@ -699,6 +699,7 @@ func (daemon *Daemon) connectToNetwork(container *container.Container, idOrName
 		return derr.ErrorCodeJoinInfo.WithArgs(err)
 	}
 
+	daemon.LogNetworkEventWithAttributes(n, "connect", map[string]string{"container": container.ID})
 	return nil
 }
 
@@ -850,11 +851,15 @@ func (daemon *Daemon) releaseNetwork(container *container.Container) {
 
 	sid := container.NetworkSettings.SandboxID
 	settings := container.NetworkSettings.Networks
+	var networks []libnetwork.Network
 	for n := range settings {
+		if nw, err := daemon.FindNetwork(n); err == nil {
+			networks = append(networks, nw)
+		}
 		settings[n] = &networktypes.EndpointSettings{}
 	}
 
-	container.NetworkSettings = &network.Settings{Networks: networks}
+	container.NetworkSettings = &network.Settings{Networks: settings}
 
 	if sid == "" || len(settings) == 0 {
 		return
@@ -873,8 +878,8 @@ func (daemon *Daemon) releaseNetwork(container *container.Container) {
 	attributes := map[string]string{
 		"container": container.ID,
 	}
-	for nwID := range settings {
-		daemon.logNetworkEventWithID(nwID, "disconnect", attributes)
+	for _, nw := range networks {
+		daemon.LogNetworkEventWithAttributes(nw, "disconnect", attributes)
 	}
 }
 

+ 1 - 5
daemon/events.go

@@ -61,12 +61,8 @@ func (daemon *Daemon) LogNetworkEvent(nw libnetwork.Network, action string) {
 func (daemon *Daemon) LogNetworkEventWithAttributes(nw libnetwork.Network, action string, attributes map[string]string) {
 	attributes["name"] = nw.Name()
 	attributes["type"] = nw.Type()
-	daemon.logNetworkEventWithID(nw.ID(), action, attributes)
-}
-
-func (daemon *Daemon) logNetworkEventWithID(id, action string, attributes map[string]string) {
 	actor := events.Actor{
-		ID:         id,
+		ID:         nw.ID(),
 		Attributes: attributes,
 	}
 	daemon.EventsService.Log(action, events.NetworkEventType, actor)

+ 27 - 1
daemon/network.go

@@ -7,6 +7,8 @@ import (
 	"strings"
 
 	"github.com/docker/docker/api/types/network"
+	derr "github.com/docker/docker/errors"
+	"github.com/docker/docker/runconfig"
 	"github.com/docker/libnetwork"
 )
 
@@ -114,7 +116,13 @@ func (daemon *Daemon) CreateNetwork(name, driver string, ipam network.IPAM, opti
 
 	nwOptions = append(nwOptions, libnetwork.NetworkOptionIpam(ipam.Driver, "", v4Conf, v6Conf))
 	nwOptions = append(nwOptions, libnetwork.NetworkOptionDriverOpts(options))
-	return c.NewNetwork(driver, name, nwOptions...)
+	n, err := c.NewNetwork(driver, name, nwOptions...)
+	if err != nil {
+		return nil, err
+	}
+
+	daemon.LogNetworkEvent(n, "create")
+	return n, nil
 }
 
 func getIpamConfig(data []network.IPAMConfig) ([]*libnetwork.IpamConf, []*libnetwork.IpamConf, error) {
@@ -178,3 +186,21 @@ func (daemon *Daemon) GetNetworkDriverList() map[string]bool {
 
 	return pluginList
 }
+
+// DeleteNetwork destroys a network unless it's one of docker's predefined networks.
+func (daemon *Daemon) DeleteNetwork(networkID string) error {
+	nw, err := daemon.FindNetwork(networkID)
+	if err != nil {
+		return err
+	}
+
+	if runconfig.IsPreDefinedNetwork(nw.Name()) {
+		return derr.ErrorCodeCantDeletePredefinedNetwork.WithArgs(nw.Name())
+	}
+
+	if err := nw.Delete(); err != nil {
+		return err
+	}
+	daemon.LogNetworkEvent(nw, "destroy")
+	return nil
+}

+ 9 - 0
errors/daemon.go

@@ -939,4 +939,13 @@ var (
 		Description:    "There was an error while trying to start a container",
 		HTTPStatusCode: http.StatusInternalServerError,
 	})
+
+	// ErrorCodeCantDeletePredefinedNetwork is generated when one of the predefined networks
+	// is attempted to be deleted.
+	ErrorCodeCantDeletePredefinedNetwork = errcode.Register(errGroup, errcode.ErrorDescriptor{
+		Value:          "CANT_DELETE_PREDEFINED_NETWORK",
+		Message:        "%s is a pre-defined network and cannot be removed",
+		Description:    "Engine's predefined networks cannot be deleted",
+		HTTPStatusCode: http.StatusForbidden,
+	})
 )

+ 26 - 0
integration-cli/docker_cli_events_unix_test.go

@@ -177,3 +177,29 @@ func (s *DockerSuite) TestVolumeEvents(c *check.C) {
 	c.Assert(volumeEvents[2], checker.Equals, "unmount")
 	c.Assert(volumeEvents[3], checker.Equals, "destroy")
 }
+
+func (s *DockerSuite) TestNetworkEvents(c *check.C) {
+	testRequires(c, DaemonIsLinux)
+
+	since := daemonTime(c).Unix()
+
+	// Observe create/connect network actions
+	dockerCmd(c, "network", "create", "test-event-network-local")
+	dockerCmd(c, "run", "--name", "test-network-container", "--net", "test-event-network-local", "-d", "busybox", "true")
+	waitRun("test-network-container")
+
+	// Observe disconnect/destroy network actions
+	dockerCmd(c, "rm", "-f", "test-network-container")
+	dockerCmd(c, "network", "rm", "test-event-network-local")
+
+	out, _ := dockerCmd(c, "events", fmt.Sprintf("--since=%d", since), fmt.Sprintf("--until=%d", daemonTime(c).Unix()))
+	events := strings.Split(strings.TrimSpace(out), "\n")
+	c.Assert(len(events), checker.GreaterThan, 4)
+
+	netEvents := eventActionsByIDAndType(c, events, "test-event-network-local", "network")
+	c.Assert(netEvents, checker.HasLen, 4)
+	c.Assert(netEvents[0], checker.Equals, "create")
+	c.Assert(netEvents[1], checker.Equals, "connect")
+	c.Assert(netEvents[2], checker.Equals, "disconnect")
+	c.Assert(netEvents[3], checker.Equals, "destroy")
+}