Browse code

Move "delete" to daemon/delete.go

This is part of an effort to break apart the deprecated server/ package

Docker-DCO-1.1-Signed-off-by: Solomon Hykes <solomon@docker.com> (github: shykes)

Fix issues with renaming container_delete to delete
Docker-DCO-1.1-Signed-off-by: Tibor Vass <teabee89@gmail.com> (github: tiborvass)

Solomon Hykes authored on 2014/08/01 06:12:12
Showing 7 changed files
... ...
@@ -678,7 +678,7 @@ func deleteContainers(eng *engine.Engine, version version.Version, w http.Respon
678 678
 	if vars == nil {
679 679
 		return fmt.Errorf("Missing parameter")
680 680
 	}
681
-	job := eng.Job("container_delete", vars["name"])
681
+	job := eng.Job("delete", vars["name"])
682 682
 
683 683
 	if version.GreaterThanOrEqualTo("1.14") {
684 684
 		job.Setenv("stop", r.Form.Get("stop"))
... ...
@@ -455,7 +455,7 @@ func TestDeleteContainers(t *testing.T) {
455 455
 	eng := engine.New()
456 456
 	name := "foo"
457 457
 	var called bool
458
-	eng.Register("container_delete", func(job *engine.Job) engine.Status {
458
+	eng.Register("delete", func(job *engine.Job) engine.Status {
459 459
 		called = true
460 460
 		if len(job.Args) == 0 {
461 461
 			t.Fatalf("Job arguments is empty")
... ...
@@ -480,7 +480,7 @@ func TestDeleteContainersWithStopAndKill(t *testing.T) {
480 480
 	}
481 481
 	eng := engine.New()
482 482
 	var called bool
483
-	eng.Register("container_delete", func(job *engine.Job) engine.Status {
483
+	eng.Register("delete", func(job *engine.Job) engine.Status {
484 484
 		called = true
485 485
 		return engine.StatusOK
486 486
 	})
... ...
@@ -147,6 +147,11 @@ func (daemon *Daemon) Install(eng *engine.Engine) error {
147 147
 	if err := eng.Register("logs", daemon.ContainerLogs); err != nil {
148 148
 		return err
149 149
 	}
150
+	// FIXME: rename "delete" to "rm" for consistency with the CLI command
151
+	// FIXME: rename ContainerDestroy to ContainerRm for consistency with the CLI command
152
+	if err := eng.Register("delete", daemon.ContainerDestroy); err != nil {
153
+		return err
154
+	}
150 155
 	return nil
151 156
 }
152 157
 
... ...
@@ -309,47 +314,6 @@ func (daemon *Daemon) LogToDisk(src *broadcastwriter.BroadcastWriter, dst, strea
309 309
 	return nil
310 310
 }
311 311
 
312
-// Destroy unregisters a container from the daemon and cleanly removes its contents from the filesystem.
313
-func (daemon *Daemon) Destroy(container *Container) error {
314
-	if container == nil {
315
-		return fmt.Errorf("The given container is <nil>")
316
-	}
317
-
318
-	element := daemon.containers.Get(container.ID)
319
-	if element == nil {
320
-		return fmt.Errorf("Container %v not found - maybe it was already destroyed?", container.ID)
321
-	}
322
-
323
-	if err := container.Stop(3); err != nil {
324
-		return err
325
-	}
326
-
327
-	// Deregister the container before removing its directory, to avoid race conditions
328
-	daemon.idIndex.Delete(container.ID)
329
-	daemon.containers.Delete(container.ID)
330
-
331
-	if _, err := daemon.containerGraph.Purge(container.ID); err != nil {
332
-		utils.Debugf("Unable to remove container from link graph: %s", err)
333
-	}
334
-
335
-	if err := daemon.driver.Remove(container.ID); err != nil {
336
-		return fmt.Errorf("Driver %s failed to remove root filesystem %s: %s", daemon.driver, container.ID, err)
337
-	}
338
-
339
-	initID := fmt.Sprintf("%s-init", container.ID)
340
-	if err := daemon.driver.Remove(initID); err != nil {
341
-		return fmt.Errorf("Driver %s failed to remove init filesystem %s: %s", daemon.driver, initID, err)
342
-	}
343
-
344
-	if err := os.RemoveAll(container.root); err != nil {
345
-		return fmt.Errorf("Unable to remove filesystem for %v: %v", container.ID, err)
346
-	}
347
-
348
-	selinuxFreeLxcContexts(container.ProcessLabel)
349
-
350
-	return nil
351
-}
352
-
353 312
 func (daemon *Daemon) restore() error {
354 313
 	var (
355 314
 		debug             = (os.Getenv("DEBUG") != "" || os.Getenv("TEST") != "")
356 315
new file mode 100644
... ...
@@ -0,0 +1,181 @@
0
+package daemon
1
+
2
+import (
3
+	"fmt"
4
+	"log"
5
+	"os"
6
+	"path"
7
+	"path/filepath"
8
+	"strings"
9
+
10
+	"github.com/docker/docker/engine"
11
+	"github.com/docker/docker/utils"
12
+)
13
+
14
+// FIXME: rename to ContainerRemove for consistency with the CLI command.
15
+func (daemon *Daemon) ContainerDestroy(job *engine.Job) engine.Status {
16
+	if len(job.Args) != 1 {
17
+		return job.Errorf("Not enough arguments. Usage: %s CONTAINER\n", job.Name)
18
+	}
19
+	name := job.Args[0]
20
+	removeVolume := job.GetenvBool("removeVolume")
21
+	removeLink := job.GetenvBool("removeLink")
22
+	stop := job.GetenvBool("stop")
23
+	kill := job.GetenvBool("kill")
24
+
25
+	container := daemon.Get(name)
26
+
27
+	if removeLink {
28
+		if container == nil {
29
+			return job.Errorf("No such link: %s", name)
30
+		}
31
+		name, err := GetFullContainerName(name)
32
+		if err != nil {
33
+			job.Error(err)
34
+		}
35
+		parent, n := path.Split(name)
36
+		if parent == "/" {
37
+			return job.Errorf("Conflict, cannot remove the default name of the container")
38
+		}
39
+		pe := daemon.ContainerGraph().Get(parent)
40
+		if pe == nil {
41
+			return job.Errorf("Cannot get parent %s for name %s", parent, name)
42
+		}
43
+		parentContainer := daemon.Get(pe.ID())
44
+
45
+		if parentContainer != nil {
46
+			parentContainer.DisableLink(n)
47
+		}
48
+
49
+		if err := daemon.ContainerGraph().Delete(name); err != nil {
50
+			return job.Error(err)
51
+		}
52
+		return engine.StatusOK
53
+	}
54
+
55
+	if container != nil {
56
+		if container.State.IsRunning() {
57
+			if stop {
58
+				if err := container.Stop(5); err != nil {
59
+					return job.Errorf("Could not stop running container, cannot remove - %v", err)
60
+				}
61
+			} else if kill {
62
+				if err := container.Kill(); err != nil {
63
+					return job.Errorf("Could not kill running container, cannot remove - %v", err)
64
+				}
65
+			} else {
66
+				return job.Errorf("You cannot remove a running container. Stop the container before attempting removal or use -s or -k")
67
+			}
68
+		}
69
+		if err := daemon.Destroy(container); err != nil {
70
+			return job.Errorf("Cannot destroy container %s: %s", name, err)
71
+		}
72
+		job.Eng.Job("log", "destroy", container.ID, daemon.Repositories().ImageName(container.Image)).Run()
73
+
74
+		if removeVolume {
75
+			var (
76
+				volumes     = make(map[string]struct{})
77
+				binds       = make(map[string]struct{})
78
+				usedVolumes = make(map[string]*Container)
79
+			)
80
+
81
+			// the volume id is always the base of the path
82
+			getVolumeId := func(p string) string {
83
+				return filepath.Base(strings.TrimSuffix(p, "/layer"))
84
+			}
85
+
86
+			// populate bind map so that they can be skipped and not removed
87
+			for _, bind := range container.HostConfig().Binds {
88
+				source := strings.Split(bind, ":")[0]
89
+				// TODO: refactor all volume stuff, all of it
90
+				// it is very important that we eval the link or comparing the keys to container.Volumes will not work
91
+				//
92
+				// eval symlink can fail, ref #5244 if we receive an is not exist error we can ignore it
93
+				p, err := filepath.EvalSymlinks(source)
94
+				if err != nil && !os.IsNotExist(err) {
95
+					return job.Error(err)
96
+				}
97
+				if p != "" {
98
+					source = p
99
+				}
100
+				binds[source] = struct{}{}
101
+			}
102
+
103
+			// Store all the deleted containers volumes
104
+			for _, volumeId := range container.Volumes {
105
+				// Skip the volumes mounted from external
106
+				// bind mounts here will will be evaluated for a symlink
107
+				if _, exists := binds[volumeId]; exists {
108
+					continue
109
+				}
110
+
111
+				volumeId = getVolumeId(volumeId)
112
+				volumes[volumeId] = struct{}{}
113
+			}
114
+
115
+			// Retrieve all volumes from all remaining containers
116
+			for _, container := range daemon.List() {
117
+				for _, containerVolumeId := range container.Volumes {
118
+					containerVolumeId = getVolumeId(containerVolumeId)
119
+					usedVolumes[containerVolumeId] = container
120
+				}
121
+			}
122
+
123
+			for volumeId := range volumes {
124
+				// If the requested volu
125
+				if c, exists := usedVolumes[volumeId]; exists {
126
+					log.Printf("The volume %s is used by the container %s. Impossible to remove it. Skipping.\n", volumeId, c.ID)
127
+					continue
128
+				}
129
+				if err := daemon.Volumes().Delete(volumeId); err != nil {
130
+					return job.Errorf("Error calling volumes.Delete(%q): %v", volumeId, err)
131
+				}
132
+			}
133
+		}
134
+	} else {
135
+		return job.Errorf("No such container: %s", name)
136
+	}
137
+	return engine.StatusOK
138
+}
139
+
140
+// Destroy unregisters a container from the daemon and cleanly removes its contents from the filesystem.
141
+// FIXME: rename to Rm for consistency with the CLI command
142
+func (daemon *Daemon) Destroy(container *Container) error {
143
+	if container == nil {
144
+		return fmt.Errorf("The given container is <nil>")
145
+	}
146
+
147
+	element := daemon.containers.Get(container.ID)
148
+	if element == nil {
149
+		return fmt.Errorf("Container %v not found - maybe it was already destroyed?", container.ID)
150
+	}
151
+
152
+	if err := container.Stop(3); err != nil {
153
+		return err
154
+	}
155
+
156
+	// Deregister the container before removing its directory, to avoid race conditions
157
+	daemon.idIndex.Delete(container.ID)
158
+	daemon.containers.Delete(container.ID)
159
+
160
+	if _, err := daemon.containerGraph.Purge(container.ID); err != nil {
161
+		utils.Debugf("Unable to remove container from link graph: %s", err)
162
+	}
163
+
164
+	if err := daemon.driver.Remove(container.ID); err != nil {
165
+		return fmt.Errorf("Driver %s failed to remove root filesystem %s: %s", daemon.driver, container.ID, err)
166
+	}
167
+
168
+	initID := fmt.Sprintf("%s-init", container.ID)
169
+	if err := daemon.driver.Remove(initID); err != nil {
170
+		return fmt.Errorf("Driver %s failed to remove init filesystem %s: %s", daemon.driver, initID, err)
171
+	}
172
+
173
+	if err := os.RemoveAll(container.root); err != nil {
174
+		return fmt.Errorf("Unable to remove filesystem for %v: %v", container.ID, err)
175
+	}
176
+
177
+	selinuxFreeLxcContexts(container.ProcessLabel)
178
+
179
+	return nil
180
+}
... ...
@@ -221,7 +221,7 @@ func TestCreateStartRestartStopStartKillRm(t *testing.T) {
221 221
 	}
222 222
 
223 223
 	// FIXME: this failed once with a race condition ("Unable to remove filesystem for xxx: directory not empty")
224
-	job = eng.Job("container_delete", id)
224
+	job = eng.Job("delete", id)
225 225
 	job.SetenvBool("removeVolume", true)
226 226
 	if err := job.Run(); err != nil {
227 227
 		t.Fatal(err)
... ...
@@ -8,11 +8,7 @@ import (
8 8
 	"errors"
9 9
 	"fmt"
10 10
 	"io"
11
-	"log"
12
-	"os"
13 11
 	"os/exec"
14
-	"path"
15
-	"path/filepath"
16 12
 	"strconv"
17 13
 	"strings"
18 14
 
... ...
@@ -223,131 +219,6 @@ func (srv *Server) Containers(job *engine.Job) engine.Status {
223 223
 	return engine.StatusOK
224 224
 }
225 225
 
226
-func (srv *Server) ContainerDestroy(job *engine.Job) engine.Status {
227
-	if len(job.Args) != 1 {
228
-		return job.Errorf("Not enough arguments. Usage: %s CONTAINER\n", job.Name)
229
-	}
230
-	name := job.Args[0]
231
-	removeVolume := job.GetenvBool("removeVolume")
232
-	removeLink := job.GetenvBool("removeLink")
233
-	stop := job.GetenvBool("stop")
234
-	kill := job.GetenvBool("kill")
235
-
236
-	container := srv.daemon.Get(name)
237
-
238
-	if removeLink {
239
-		if container == nil {
240
-			return job.Errorf("No such link: %s", name)
241
-		}
242
-		name, err := daemon.GetFullContainerName(name)
243
-		if err != nil {
244
-			job.Error(err)
245
-		}
246
-		parent, n := path.Split(name)
247
-		if parent == "/" {
248
-			return job.Errorf("Conflict, cannot remove the default name of the container")
249
-		}
250
-		pe := srv.daemon.ContainerGraph().Get(parent)
251
-		if pe == nil {
252
-			return job.Errorf("Cannot get parent %s for name %s", parent, name)
253
-		}
254
-		parentContainer := srv.daemon.Get(pe.ID())
255
-
256
-		if parentContainer != nil {
257
-			parentContainer.DisableLink(n)
258
-		}
259
-
260
-		if err := srv.daemon.ContainerGraph().Delete(name); err != nil {
261
-			return job.Error(err)
262
-		}
263
-		return engine.StatusOK
264
-	}
265
-
266
-	if container != nil {
267
-		if container.State.IsRunning() {
268
-			if stop {
269
-				if err := container.Stop(5); err != nil {
270
-					return job.Errorf("Could not stop running container, cannot remove - %v", err)
271
-				}
272
-			} else if kill {
273
-				if err := container.Kill(); err != nil {
274
-					return job.Errorf("Could not kill running container, cannot remove - %v", err)
275
-				}
276
-			} else {
277
-				return job.Errorf("You cannot remove a running container. Stop the container before attempting removal or use -s or -k")
278
-			}
279
-		}
280
-		if err := srv.daemon.Destroy(container); err != nil {
281
-			return job.Errorf("Cannot destroy container %s: %s", name, err)
282
-		}
283
-		srv.LogEvent("destroy", container.ID, srv.daemon.Repositories().ImageName(container.Image))
284
-
285
-		if removeVolume {
286
-			var (
287
-				volumes     = make(map[string]struct{})
288
-				binds       = make(map[string]struct{})
289
-				usedVolumes = make(map[string]*daemon.Container)
290
-			)
291
-
292
-			// the volume id is always the base of the path
293
-			getVolumeId := func(p string) string {
294
-				return filepath.Base(strings.TrimSuffix(p, "/layer"))
295
-			}
296
-
297
-			// populate bind map so that they can be skipped and not removed
298
-			for _, bind := range container.HostConfig().Binds {
299
-				source := strings.Split(bind, ":")[0]
300
-				// TODO: refactor all volume stuff, all of it
301
-				// it is very important that we eval the link or comparing the keys to container.Volumes will not work
302
-				//
303
-				// eval symlink can fail, ref #5244 if we receive an is not exist error we can ignore it
304
-				p, err := filepath.EvalSymlinks(source)
305
-				if err != nil && !os.IsNotExist(err) {
306
-					return job.Error(err)
307
-				}
308
-				if p != "" {
309
-					source = p
310
-				}
311
-				binds[source] = struct{}{}
312
-			}
313
-
314
-			// Store all the deleted containers volumes
315
-			for _, volumeId := range container.Volumes {
316
-				// Skip the volumes mounted from external
317
-				// bind mounts here will will be evaluated for a symlink
318
-				if _, exists := binds[volumeId]; exists {
319
-					continue
320
-				}
321
-
322
-				volumeId = getVolumeId(volumeId)
323
-				volumes[volumeId] = struct{}{}
324
-			}
325
-
326
-			// Retrieve all volumes from all remaining containers
327
-			for _, container := range srv.daemon.List() {
328
-				for _, containerVolumeId := range container.Volumes {
329
-					containerVolumeId = getVolumeId(containerVolumeId)
330
-					usedVolumes[containerVolumeId] = container
331
-				}
332
-			}
333
-
334
-			for volumeId := range volumes {
335
-				// If the requested volu
336
-				if c, exists := usedVolumes[volumeId]; exists {
337
-					log.Printf("The volume %s is used by the container %s. Impossible to remove it. Skipping.\n", volumeId, c.ID)
338
-					continue
339
-				}
340
-				if err := srv.daemon.Volumes().Delete(volumeId); err != nil {
341
-					return job.Errorf("Error calling volumes.Delete(%q): %v", volumeId, err)
342
-				}
343
-			}
344
-		}
345
-	} else {
346
-		return job.Errorf("No such container: %s", name)
347
-	}
348
-	return engine.StatusOK
349
-}
350
-
351 226
 func (srv *Server) ContainerCopy(job *engine.Job) engine.Status {
352 227
 	if len(job.Args) != 2 {
353 228
 		return job.Errorf("Usage: %s CONTAINER RESOURCE\n", job.Name)
... ...
@@ -86,25 +86,24 @@ func InitServer(job *engine.Job) engine.Status {
86 86
 	job.Eng.Hack_SetGlobalVar("httpapi.daemon", srv.daemon)
87 87
 
88 88
 	for name, handler := range map[string]engine.Handler{
89
-		"tag":              srv.ImageTag, // FIXME merge with "image_tag"
90
-		"info":             srv.DockerInfo,
91
-		"container_delete": srv.ContainerDestroy,
92
-		"image_export":     srv.ImageExport,
93
-		"images":           srv.Images,
94
-		"history":          srv.ImageHistory,
95
-		"viz":              srv.ImagesViz,
96
-		"container_copy":   srv.ContainerCopy,
97
-		"log":              srv.Log,
98
-		"changes":          srv.ContainerChanges,
99
-		"top":              srv.ContainerTop,
100
-		"load":             srv.ImageLoad,
101
-		"build":            srv.Build,
102
-		"pull":             srv.ImagePull,
103
-		"import":           srv.ImageImport,
104
-		"image_delete":     srv.ImageDelete,
105
-		"events":           srv.Events,
106
-		"push":             srv.ImagePush,
107
-		"containers":       srv.Containers,
89
+		"tag":            srv.ImageTag, // FIXME merge with "image_tag"
90
+		"info":           srv.DockerInfo,
91
+		"image_export":   srv.ImageExport,
92
+		"images":         srv.Images,
93
+		"history":        srv.ImageHistory,
94
+		"viz":            srv.ImagesViz,
95
+		"container_copy": srv.ContainerCopy,
96
+		"log":            srv.Log,
97
+		"changes":        srv.ContainerChanges,
98
+		"top":            srv.ContainerTop,
99
+		"load":           srv.ImageLoad,
100
+		"build":          srv.Build,
101
+		"pull":           srv.ImagePull,
102
+		"import":         srv.ImageImport,
103
+		"image_delete":   srv.ImageDelete,
104
+		"events":         srv.Events,
105
+		"push":           srv.ImagePush,
106
+		"containers":     srv.Containers,
108 107
 	} {
109 108
 		if err := job.Eng.Register(name, srv.handlerWrap(handler)); err != nil {
110 109
 			return job.Error(err)