Browse code

Log and print original error for `start`

Currently `start` will hide some errors and throw a consolidated error,
which will make it hard to debug because developer can't find the
original error.

This commit allow daemon to log original errors first.

Signed-off-by: Zhang Wei <zhangwei555@huawei.com>

Zhang Wei authored on 2016/06/01 00:18:17
Showing 2 changed files
... ...
@@ -7,6 +7,7 @@ import (
7 7
 	"os"
8 8
 	"runtime"
9 9
 	"strings"
10
+	"syscall"
10 11
 
11 12
 	"golang.org/x/net/context"
12 13
 
... ...
@@ -315,18 +316,18 @@ func reportError(stderr io.Writer, name string, str string, withHelp bool) {
315 315
 	fmt.Fprintf(stderr, "%s: %s.\n", os.Args[0], str)
316 316
 }
317 317
 
318
-// if container start fails with 'command not found' error, return 127
319
-// if container start fails with 'command cannot be invoked' error, return 126
318
+// if container start fails with 'not found'/'no such' error, return 127
319
+// if container start fails with 'permission denied' error, return 126
320 320
 // return 125 for generic docker daemon failures
321 321
 func runStartContainerErr(err error) error {
322 322
 	trimmedErr := strings.TrimPrefix(err.Error(), "Error response from daemon: ")
323 323
 	statusError := cli.StatusError{StatusCode: 125}
324
-	if strings.HasPrefix(trimmedErr, "Container command") {
325
-		if strings.Contains(trimmedErr, errCmdNotFound) {
326
-			statusError = cli.StatusError{StatusCode: 127}
327
-		} else if strings.Contains(trimmedErr, errCmdCouldNotBeInvoked) {
328
-			statusError = cli.StatusError{StatusCode: 126}
329
-		}
324
+	if strings.Contains(trimmedErr, "executable file not found") ||
325
+		strings.Contains(trimmedErr, "no such file or directory") ||
326
+		strings.Contains(trimmedErr, "system cannot find the file specified") {
327
+		statusError = cli.StatusError{StatusCode: 127}
328
+	} else if strings.Contains(trimmedErr, syscall.EACCES.Error()) {
329
+		statusError = cli.StatusError{StatusCode: 126}
330 330
 	}
331 331
 
332 332
 	return statusError
... ...
@@ -7,6 +7,8 @@ import (
7 7
 	"strings"
8 8
 	"syscall"
9 9
 
10
+	"google.golang.org/grpc"
11
+
10 12
 	"github.com/Sirupsen/logrus"
11 13
 	"github.com/docker/docker/container"
12 14
 	"github.com/docker/docker/errors"
... ...
@@ -131,24 +133,24 @@ func (daemon *Daemon) containerStart(container *container.Container) (err error)
131 131
 	}
132 132
 
133 133
 	if err := daemon.containerd.Create(container.ID, *spec, libcontainerd.WithRestartManager(container.RestartManager(true))); err != nil {
134
+		errDesc := grpc.ErrorDesc(err)
135
+		logrus.Errorf("Create container failed with error: %s", errDesc)
134 136
 		// if we receive an internal error from the initial start of a container then lets
135 137
 		// return it instead of entering the restart loop
136 138
 		// set to 127 for container cmd not found/does not exist)
137
-		if strings.Contains(err.Error(), "executable file not found") ||
138
-			strings.Contains(err.Error(), "no such file or directory") ||
139
-			strings.Contains(err.Error(), "system cannot find the file specified") {
139
+		if strings.Contains(errDesc, "executable file not found") ||
140
+			strings.Contains(errDesc, "no such file or directory") ||
141
+			strings.Contains(errDesc, "system cannot find the file specified") {
140 142
 			container.ExitCode = 127
141
-			err = fmt.Errorf("Container command '%s' not found or does not exist", container.Path)
142 143
 		}
143 144
 		// set to 126 for container cmd can't be invoked errors
144
-		if strings.Contains(err.Error(), syscall.EACCES.Error()) {
145
+		if strings.Contains(errDesc, syscall.EACCES.Error()) {
145 146
 			container.ExitCode = 126
146
-			err = fmt.Errorf("Container command '%s' could not be invoked", container.Path)
147 147
 		}
148 148
 
149 149
 		container.Reset(false)
150 150
 
151
-		return err
151
+		return fmt.Errorf("%s", errDesc)
152 152
 	}
153 153
 
154 154
 	return nil