Browse code

Add network events.

Signed-off-by: David Calavera <david.calavera@gmail.com>

David Calavera authored on 2015/12/22 13:35:30
Showing 7 changed files
... ...
@@ -19,4 +19,5 @@ type Backend interface {
19 19
 	DisconnectContainerFromNetwork(containerName string,
20 20
 		network libnetwork.Network) error
21 21
 	NetworkControllerEnabled() bool
22
+	DeleteNetwork(name string) error
22 23
 }
... ...
@@ -148,21 +148,7 @@ func (n *networkRouter) postNetworkDisconnect(ctx context.Context, w http.Respon
148 148
 }
149 149
 
150 150
 func (n *networkRouter) deleteNetwork(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
151
-	if err := httputils.ParseForm(r); err != nil {
152
-		return err
153
-	}
154
-
155
-	nw, err := n.backend.FindNetwork(vars["id"])
156
-	if err != nil {
157
-		return err
158
-	}
159
-
160
-	if runconfig.IsPreDefinedNetwork(nw.Name()) {
161
-		return httputils.WriteJSON(w, http.StatusForbidden,
162
-			fmt.Sprintf("%s is a pre-defined network and cannot be removed", nw.Name()))
163
-	}
164
-
165
-	return nw.Delete()
151
+	return n.backend.DeleteNetwork(vars["id"])
166 152
 }
167 153
 
168 154
 func buildNetworkResource(nw libnetwork.Network) *types.NetworkResource {
... ...
@@ -699,6 +699,7 @@ func (daemon *Daemon) connectToNetwork(container *container.Container, idOrName
699 699
 		return derr.ErrorCodeJoinInfo.WithArgs(err)
700 700
 	}
701 701
 
702
+	daemon.LogNetworkEventWithAttributes(n, "connect", map[string]string{"container": container.ID})
702 703
 	return nil
703 704
 }
704 705
 
... ...
@@ -850,11 +851,15 @@ func (daemon *Daemon) releaseNetwork(container *container.Container) {
850 850
 
851 851
 	sid := container.NetworkSettings.SandboxID
852 852
 	settings := container.NetworkSettings.Networks
853
+	var networks []libnetwork.Network
853 854
 	for n := range settings {
855
+		if nw, err := daemon.FindNetwork(n); err == nil {
856
+			networks = append(networks, nw)
857
+		}
854 858
 		settings[n] = &networktypes.EndpointSettings{}
855 859
 	}
856 860
 
857
-	container.NetworkSettings = &network.Settings{Networks: networks}
861
+	container.NetworkSettings = &network.Settings{Networks: settings}
858 862
 
859 863
 	if sid == "" || len(settings) == 0 {
860 864
 		return
... ...
@@ -873,8 +878,8 @@ func (daemon *Daemon) releaseNetwork(container *container.Container) {
873 873
 	attributes := map[string]string{
874 874
 		"container": container.ID,
875 875
 	}
876
-	for nwID := range settings {
877
-		daemon.logNetworkEventWithID(nwID, "disconnect", attributes)
876
+	for _, nw := range networks {
877
+		daemon.LogNetworkEventWithAttributes(nw, "disconnect", attributes)
878 878
 	}
879 879
 }
880 880
 
... ...
@@ -61,12 +61,8 @@ func (daemon *Daemon) LogNetworkEvent(nw libnetwork.Network, action string) {
61 61
 func (daemon *Daemon) LogNetworkEventWithAttributes(nw libnetwork.Network, action string, attributes map[string]string) {
62 62
 	attributes["name"] = nw.Name()
63 63
 	attributes["type"] = nw.Type()
64
-	daemon.logNetworkEventWithID(nw.ID(), action, attributes)
65
-}
66
-
67
-func (daemon *Daemon) logNetworkEventWithID(id, action string, attributes map[string]string) {
68 64
 	actor := events.Actor{
69
-		ID:         id,
65
+		ID:         nw.ID(),
70 66
 		Attributes: attributes,
71 67
 	}
72 68
 	daemon.EventsService.Log(action, events.NetworkEventType, actor)
... ...
@@ -7,6 +7,8 @@ import (
7 7
 	"strings"
8 8
 
9 9
 	"github.com/docker/docker/api/types/network"
10
+	derr "github.com/docker/docker/errors"
11
+	"github.com/docker/docker/runconfig"
10 12
 	"github.com/docker/libnetwork"
11 13
 )
12 14
 
... ...
@@ -114,7 +116,13 @@ func (daemon *Daemon) CreateNetwork(name, driver string, ipam network.IPAM, opti
114 114
 
115 115
 	nwOptions = append(nwOptions, libnetwork.NetworkOptionIpam(ipam.Driver, "", v4Conf, v6Conf))
116 116
 	nwOptions = append(nwOptions, libnetwork.NetworkOptionDriverOpts(options))
117
-	return c.NewNetwork(driver, name, nwOptions...)
117
+	n, err := c.NewNetwork(driver, name, nwOptions...)
118
+	if err != nil {
119
+		return nil, err
120
+	}
121
+
122
+	daemon.LogNetworkEvent(n, "create")
123
+	return n, nil
118 124
 }
119 125
 
120 126
 func getIpamConfig(data []network.IPAMConfig) ([]*libnetwork.IpamConf, []*libnetwork.IpamConf, error) {
... ...
@@ -178,3 +186,21 @@ func (daemon *Daemon) GetNetworkDriverList() map[string]bool {
178 178
 
179 179
 	return pluginList
180 180
 }
181
+
182
+// DeleteNetwork destroys a network unless it's one of docker's predefined networks.
183
+func (daemon *Daemon) DeleteNetwork(networkID string) error {
184
+	nw, err := daemon.FindNetwork(networkID)
185
+	if err != nil {
186
+		return err
187
+	}
188
+
189
+	if runconfig.IsPreDefinedNetwork(nw.Name()) {
190
+		return derr.ErrorCodeCantDeletePredefinedNetwork.WithArgs(nw.Name())
191
+	}
192
+
193
+	if err := nw.Delete(); err != nil {
194
+		return err
195
+	}
196
+	daemon.LogNetworkEvent(nw, "destroy")
197
+	return nil
198
+}
... ...
@@ -939,4 +939,13 @@ var (
939 939
 		Description:    "There was an error while trying to start a container",
940 940
 		HTTPStatusCode: http.StatusInternalServerError,
941 941
 	})
942
+
943
+	// ErrorCodeCantDeletePredefinedNetwork is generated when one of the predefined networks
944
+	// is attempted to be deleted.
945
+	ErrorCodeCantDeletePredefinedNetwork = errcode.Register(errGroup, errcode.ErrorDescriptor{
946
+		Value:          "CANT_DELETE_PREDEFINED_NETWORK",
947
+		Message:        "%s is a pre-defined network and cannot be removed",
948
+		Description:    "Engine's predefined networks cannot be deleted",
949
+		HTTPStatusCode: http.StatusForbidden,
950
+	})
942 951
 )
... ...
@@ -177,3 +177,29 @@ func (s *DockerSuite) TestVolumeEvents(c *check.C) {
177 177
 	c.Assert(volumeEvents[2], checker.Equals, "unmount")
178 178
 	c.Assert(volumeEvents[3], checker.Equals, "destroy")
179 179
 }
180
+
181
+func (s *DockerSuite) TestNetworkEvents(c *check.C) {
182
+	testRequires(c, DaemonIsLinux)
183
+
184
+	since := daemonTime(c).Unix()
185
+
186
+	// Observe create/connect network actions
187
+	dockerCmd(c, "network", "create", "test-event-network-local")
188
+	dockerCmd(c, "run", "--name", "test-network-container", "--net", "test-event-network-local", "-d", "busybox", "true")
189
+	waitRun("test-network-container")
190
+
191
+	// Observe disconnect/destroy network actions
192
+	dockerCmd(c, "rm", "-f", "test-network-container")
193
+	dockerCmd(c, "network", "rm", "test-event-network-local")
194
+
195
+	out, _ := dockerCmd(c, "events", fmt.Sprintf("--since=%d", since), fmt.Sprintf("--until=%d", daemonTime(c).Unix()))
196
+	events := strings.Split(strings.TrimSpace(out), "\n")
197
+	c.Assert(len(events), checker.GreaterThan, 4)
198
+
199
+	netEvents := eventActionsByIDAndType(c, events, "test-event-network-local", "network")
200
+	c.Assert(netEvents, checker.HasLen, 4)
201
+	c.Assert(netEvents[0], checker.Equals, "create")
202
+	c.Assert(netEvents[1], checker.Equals, "connect")
203
+	c.Assert(netEvents[2], checker.Equals, "disconnect")
204
+	c.Assert(netEvents[3], checker.Equals, "destroy")
205
+}