From 2035af44aae3664b217d6903cbf39c259f568490 Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Thu, 5 Dec 2013 02:10:41 -0700 Subject: [PATCH 1/3] Always copy dockerinit locally, regardless of whether our docker binary is static, because even it might get deleted or moved/renamed --- runtime.go | 10 +++++----- utils/utils.go | 20 +++++++++++++++++++- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/runtime.go b/runtime.go index 3268892d56..071e94acd8 100644 --- a/runtime.go +++ b/runtime.go @@ -734,18 +734,18 @@ func NewRuntimeFromDirectory(config *DaemonConfig) (*Runtime, error) { return nil, fmt.Errorf("Could not locate dockerinit: This usually means docker was built incorrectly. See http://docs.docker.io/en/latest/contributing/devenvironment for official build instructions.") } - if !utils.IAMSTATIC { - if err := os.Mkdir(path.Join(config.Root, fmt.Sprintf("init")), 0700); err != nil && !os.IsExist(err) { + if sysInitPath != localCopy { + // When we find a suitable dockerinit binary (even if it's our local binary), we copy it into config.Root at localCopy for future use (so that the original can go away without that being a problem, for example during a package upgrade). + if err := os.Mkdir(path.Dir(localCopy), 0700); err != nil && !os.IsExist(err) { return nil, err } - if _, err := utils.CopyFile(sysInitPath, localCopy); err != nil { return nil, err } - sysInitPath = localCopy - if err := os.Chmod(sysInitPath, 0700); err != nil { + if err := os.Chmod(localCopy, 0700); err != nil { return nil, err } + sysInitPath = localCopy } runtime := &Runtime{ diff --git a/utils/utils.go b/utils/utils.go index 6864dddf82..473302bc97 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -162,14 +162,23 @@ func Trunc(s string, maxlen int) string { return s[:maxlen] } -// Figure out the absolute path of our own binary +// Figure out the absolute path of our own binary (if it's still around). func SelfPath() string { path, err := exec.LookPath(os.Args[0]) if err != nil { + if os.IsNotExist(err) { + return "" + } + if execErr, ok := err.(*exec.Error); ok && os.IsNotExist(execErr.Err) { + return "" + } panic(err) } path, err = filepath.Abs(path) if err != nil { + if os.IsNotExist(err) { + return "" + } panic(err) } return path @@ -190,7 +199,13 @@ func dockerInitSha1(target string) string { } func isValidDockerInitPath(target string, selfPath string) bool { // target and selfPath should be absolute (InitPath and SelfPath already do this) + if target == "" { + return false + } if IAMSTATIC { + if selfPath == "" { + return false + } if target == selfPath { return true } @@ -229,6 +244,9 @@ func DockerInitPath(localCopy string) string { "/usr/local/lib/docker/dockerinit", } for _, dockerInit := range possibleInits { + if dockerInit == "" { + continue + } path, err := exec.LookPath(dockerInit) if err == nil { path, err = filepath.Abs(path) From f02d766f9a93bf86c6473eb2772bc239ffaa1cd6 Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Thu, 5 Dec 2013 02:14:15 -0700 Subject: [PATCH 2/3] Add dockerinit SHA1 and path to "docker info" when debug mode is enabled --- commands.go | 7 +++++++ server.go | 9 +++++++++ 2 files changed, 16 insertions(+) diff --git a/commands.go b/commands.go index ef6dce6bd5..638af7f514 100644 --- a/commands.go +++ b/commands.go @@ -469,6 +469,13 @@ func (cli *DockerCli) CmdInfo(args ...string) error { fmt.Fprintf(cli.out, "LXC Version: %s\n", remoteInfo.Get("LXCVersion")) fmt.Fprintf(cli.out, "EventsListeners: %d\n", remoteInfo.GetInt("NEventsListener")) fmt.Fprintf(cli.out, "Kernel Version: %s\n", remoteInfo.Get("KernelVersion")) + + if initSha1 := remoteInfo.Get("InitSha1"); initSha1 != "" { + fmt.Fprintf(cli.out, "Init SHA1: %s\n", initSha1) + } + if initPath := remoteInfo.Get("InitPath"); initPath != "" { + fmt.Fprintf(cli.out, "Init Path: %s\n", initPath) + } } if len(remoteInfo.GetList("IndexServerAddress")) != 0 { diff --git a/server.go b/server.go index 9b492a2927..7aa03a0374 100644 --- a/server.go +++ b/server.go @@ -634,6 +634,13 @@ func (srv *Server) DockerInfo(job *engine.Job) engine.Status { kernelVersion = kv.String() } + // if we still have the original dockerinit binary from before we copied it locally, let's return the path to that, since that's more intuitive (the copied path is trivial to derive by hand given VERSION) + initPath := utils.DockerInitPath("") + if initPath == "" { + // if that fails, we'll just return the path from the runtime + initPath = srv.runtime.sysInitPath + } + v := &engine.Env{} v.SetInt("Containers", len(srv.runtime.List())) v.SetInt("Images", imgcount) @@ -649,6 +656,8 @@ func (srv *Server) DockerInfo(job *engine.Job) engine.Status { v.SetInt("NEventsListener", len(srv.events)) v.Set("KernelVersion", kernelVersion) v.Set("IndexServerAddress", auth.IndexServerAddress()) + v.Set("InitSha1", utils.INITSHA1) + v.Set("InitPath", initPath) if _, err := v.WriteTo(job.Stdout); err != nil { job.Error(err) return engine.StatusErr From 2ed1001c57646f6869016739a8e177bb52f32e2a Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Thu, 5 Dec 2013 02:15:47 -0700 Subject: [PATCH 3/3] Allow packagers to specify a custom dockerinit lookup location via DOCKER_INITPATH in dynbinary Only necessary if distro policy dictates that the path deviate from the paths already listed in utils/utils.go - please refrain from using it otherwise. --- hack/make/dynbinary | 2 +- utils/utils.go | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/hack/make/dynbinary b/hack/make/dynbinary index 100c00eed5..2ee1ecacb3 100644 --- a/hack/make/dynbinary +++ b/hack/make/dynbinary @@ -12,6 +12,6 @@ export DOCKER_INITSHA1="$(sha1sum $DEST/dockerinit-$VERSION | cut -d' ' -f1)" # exported so that "dyntest" can easily access it later without recalculating it ( - export LDFLAGS_STATIC="-X github.com/dotcloud/docker/utils.INITSHA1 \"$DOCKER_INITSHA1\"" + export LDFLAGS_STATIC="-X github.com/dotcloud/docker/utils.INITSHA1 \"$DOCKER_INITSHA1\" -X github.com/dotcloud/docker/utils.INITPATH \"$DOCKER_INITPATH\"" source "$(dirname "$BASH_SOURCE")/binary" ) diff --git a/utils/utils.go b/utils/utils.go index 473302bc97..f6e65420e8 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -26,6 +26,7 @@ import ( var ( IAMSTATIC bool // whether or not Docker itself was compiled statically via ./hack/make.sh binary INITSHA1 string // sha1sum of separate static dockerinit, if Docker itself was compiled dynamically via ./hack/make.sh dynbinary + INITPATH string // custom location to search for a valid dockerinit binary (available for packagers as a last resort escape hatch) ) // A common interface to access the Fatal method of @@ -231,6 +232,7 @@ func DockerInitPath(localCopy string) string { } var possibleInits = []string{ localCopy, + INITPATH, filepath.Join(filepath.Dir(selfPath), "dockerinit"), // FHS 3.0 Draft: "/usr/libexec includes internal binaries that are not intended to be executed directly by users or shell scripts. Applications may use a single subdirectory under /usr/libexec."