// useDirperm checks dirperm1 mount option can be used with the current // version of aufs. func useDirperm() bool { enableDirpermLock.Do(func() { base, err := ioutil.TempDir("", "docker-aufs-base") if err != nil { logrus.Errorf("error checking dirperm1: %v", err) return } defer os.RemoveAll(base) union, err := ioutil.TempDir("", "docker-aufs-union") if err != nil { logrus.Errorf("error checking dirperm1: %v", err) return } defer os.RemoveAll(union) opts := fmt.Sprintf("br:%s,dirperm1,xino=/dev/shm/aufs.xino", base) if err := mount("none", union, "aufs", 0, opts); err != nil { return } enableDirperm = true if err := Unmount(union); err != nil { logrus.Errorf("error checking dirperm1: failed to unmount %v", err) } }) return enableDirperm }
func openNextAvailableLoopback(index int, sparseFile *os.File) (loopFile *os.File, err error) { // Start looking for a free /dev/loop for { target := fmt.Sprintf("/dev/loop%d", index) index++ fi, err := os.Stat(target) if err != nil { if os.IsNotExist(err) { log.Errorf("There are no more loopback devices available.") } return nil, ErrAttachLoopbackDevice } if fi.Mode()&os.ModeDevice != os.ModeDevice { log.Errorf("Loopback device %s is not a block device.", target) continue } // OpenFile adds O_CLOEXEC loopFile, err = os.OpenFile(target, os.O_RDWR, 0644) if err != nil { log.Errorf("Error opening loopback device: %s", err) return nil, ErrAttachLoopbackDevice } // Try to attach to the loop file if err := ioctlLoopSetFd(loopFile.Fd(), sparseFile.Fd()); err != nil { loopFile.Close() // If the error is EBUSY, then try the next loopback if err != syscall.EBUSY { log.Errorf("Cannot set up loopback device %s: %s", target, err) return nil, ErrAttachLoopbackDevice } // Otherwise, we keep going with the loop continue } // In case of success, we finished. Break the loop. break } // This can't happen, but let's be sure if loopFile == nil { log.Errorf("Unreachable code reached! Error attaching %s to a loopback device.", sparseFile.Name()) return nil, ErrAttachLoopbackDevice } return loopFile, nil }
// Write attempts to flush the events to the downstream sink until it succeeds // or the sink is closed. func (rs *retryingSink) Write(events ...Event) error { rs.mu.Lock() defer rs.mu.Unlock() retry: if rs.closed { return ErrSinkClosed } if !rs.proceed() { logrus.Warnf("%v encountered too many errors, backing off", rs.sink) rs.wait(rs.failures.backoff) goto retry } if err := rs.write(events...); err != nil { if err == ErrSinkClosed { // terminal! return err } logrus.Errorf("retryingsink: error writing events: %v, retrying", err) goto retry } return nil }
func (devices *DeviceSet) processPendingTransaction() error { if err := devices.loadTransactionMetaData(); err != nil { return err } // If there was open transaction but pool transaction Id is same // as open transaction Id, nothing to roll back. if devices.TransactionId == devices.OpenTransactionId { return nil } // If open transaction Id is less than pool transaction Id, something // is wrong. Bail out. if devices.OpenTransactionId < devices.TransactionId { log.Errorf("Open Transaction id %d is less than pool transaction id %d", devices.OpenTransactionId, devices.TransactionId) return nil } // Pool transaction Id is not same as open transaction. There is // a transaction which was not completed. if err := devices.rollbackTransaction(); err != nil { return fmt.Errorf("Rolling back open transaction failed: %s", err) } devices.OpenTransactionId = devices.TransactionId return nil }
func (pm *PortMapper) Unmap(host net.Addr) error { pm.lock.Lock() defer pm.lock.Unlock() key := getKey(host) data, exists := pm.currentMappings[key] if !exists { return ErrPortNotMapped } data.userlandProxy.Stop() delete(pm.currentMappings, key) containerIP, containerPort := getIPAndPort(data.container) hostIP, hostPort := getIPAndPort(data.host) if err := pm.forward(iptables.Delete, data.proto, hostIP, hostPort, containerIP.String(), containerPort); err != nil { log.Errorf("Error on iptables delete: %s", err) } switch a := host.(type) { case *net.TCPAddr: return pm.allocator.ReleasePort(a.IP, "tcp", a.Port) case *net.UDPAddr: return pm.allocator.ReleasePort(a.IP, "udp", a.Port) } return nil }
// getBuiltinDriver initalizes and returns the registered driver, but does not try to load from plugins func getBuiltinDriver(name, home string, options []string, uidMaps, gidMaps []idtools.IDMap) (Driver, error) { if initFunc, exists := drivers[name]; exists { return initFunc(filepath.Join(home, name), options, uidMaps, gidMaps) } logrus.Errorf("Failed to built-in GetDriver graph %s %s", name, home) return nil, ErrNotSupported }
func MatchesContentType(contentType, expectedType string) bool { mimetype, _, err := mime.ParseMediaType(contentType) if err != nil { log.Errorf("Error parsing media type: %s error: %s", contentType, err.Error()) } return err == nil && mimetype == expectedType }
// getStoredHashStates returns a slice of hashStateEntries for this upload. func (bw *blobWriter) getStoredHashStates(ctx context.Context) ([]hashStateEntry, error) { uploadHashStatePathPrefix, err := bw.blobStore.pm.path(uploadHashStatePathSpec{ name: bw.blobStore.repository.Name(), id: bw.id, alg: bw.digester.Digest().Algorithm(), list: true, }) if err != nil { return nil, err } paths, err := bw.blobStore.driver.List(ctx, uploadHashStatePathPrefix) if err != nil { if _, ok := err.(storagedriver.PathNotFoundError); !ok { return nil, err } // Treat PathNotFoundError as no entries. paths = nil } hashStateEntries := make([]hashStateEntry, 0, len(paths)) for _, p := range paths { pathSuffix := path.Base(p) // The suffix should be the offset. offset, err := strconv.ParseInt(pathSuffix, 0, 64) if err != nil { logrus.Errorf("unable to parse offset from upload state path %q: %s", p, err) } hashStateEntries = append(hashStateEntries, hashStateEntry{offset: offset, path: p}) } return hashStateEntries, nil }
func (d *Driver) Put(id string) error { err := d.DeviceSet.UnmountDevice(id) if err != nil { log.Errorf("Error unmounting device %s: %s", id, err) } return err }
func httpError(w http.ResponseWriter, err error) { statusCode := http.StatusInternalServerError // FIXME: this is brittle and should not be necessary. // If we need to differentiate between different possible error types, we should // create appropriate error types with clearly defined meaning. errStr := strings.ToLower(err.Error()) if strings.Contains(errStr, "no such") { statusCode = http.StatusNotFound } else if strings.Contains(errStr, "bad parameter") { statusCode = http.StatusBadRequest } else if strings.Contains(errStr, "conflict") { statusCode = http.StatusConflict } else if strings.Contains(errStr, "impossible") { statusCode = http.StatusNotAcceptable } else if strings.Contains(errStr, "wrong login/password") { statusCode = http.StatusUnauthorized } else if strings.Contains(errStr, "hasn't been activated") { statusCode = http.StatusForbidden } if err != nil { log.Errorf("HTTP Error: statusCode=%d %v", statusCode, err) http.Error(w, err.Error(), statusCode) } }
func (cli *DockerCli) forwardAllSignals(cid string) chan os.Signal { sigc := make(chan os.Signal, 128) signal.CatchAll(sigc) go func() { for s := range sigc { if s == signal.SIGCHLD { continue } var sig string for sigStr, sigN := range signal.SignalMap { if sigN == s { sig = sigStr break } } if sig == "" { log.Errorf("Unsupported signal: %v. Discarding.", s) } if _, _, err := readBody(cli.call("POST", fmt.Sprintf("/containers/%s/kill?signal=%s", cid, sig), nil, false)); err != nil { log.Debugf("Error sending signal: %s", err) } } }() return sigc }
func wsContainersAttach(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := parseForm(r); err != nil { return err } if vars == nil { return fmt.Errorf("Missing parameter") } if err := eng.Job("container_inspect", vars["name"]).Run(); err != nil { return err } h := websocket.Handler(func(ws *websocket.Conn) { defer ws.Close() job := eng.Job("attach", vars["name"]) job.Setenv("logs", r.Form.Get("logs")) job.Setenv("stream", r.Form.Get("stream")) job.Setenv("stdin", r.Form.Get("stdin")) job.Setenv("stdout", r.Form.Get("stdout")) job.Setenv("stderr", r.Form.Get("stderr")) job.Stdin.Add(ws) job.Stdout.Add(ws) job.Stderr.Set(ws) if err := job.Run(); err != nil { log.Errorf("Error attaching websocket: %s", err) } }) h.ServeHTTP(w, r) return nil }
func makeHttpHandler(eng *engine.Engine, logging bool, localMethod string, localRoute string, handlerFunc HttpApiFunc, corsHeaders string, dockerVersion version.Version) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { // log the request log.Debugf("Calling %s %s", localMethod, localRoute) if logging { log.Infof("%s %s", r.Method, r.RequestURI) } if strings.Contains(r.Header.Get("User-Agent"), "Docker-Client/") { userAgent := strings.Split(r.Header.Get("User-Agent"), "/") if len(userAgent) == 2 && !dockerVersion.Equal(version.Version(userAgent[1])) { log.Debugf("Warning: client and server don't have the same version (client: %s, server: %s)", userAgent[1], dockerVersion) } } version := version.Version(mux.Vars(r)["version"]) if version == "" { version = api.APIVERSION } if corsHeaders != "" { writeCorsHeaders(w, r, corsHeaders) } if version.GreaterThan(api.APIVERSION) { http.Error(w, fmt.Errorf("client and server don't have same version (client : %s, server: %s)", version, api.APIVERSION).Error(), http.StatusNotFound) return } if err := handlerFunc(eng, version, w, r, mux.Vars(r)); err != nil { log.Errorf("Handler for %s %s returned error: %s", localMethod, localRoute, err) httpError(w, err) } } }
func LoopbackSetCapacity(file *os.File) error { if err := ioctlLoopSetCapacity(file.Fd(), 0); err != nil { log.Errorf("Error loopbackSetCapacity: %s", err) return ErrLoopbackSetCapacity } return nil }
func GetTotalUsedFds() int { if fds, err := ioutil.ReadDir(fmt.Sprintf("/proc/%d/fd", os.Getpid())); err != nil { log.Errorf("Error opening /proc/%d/fd: %s", os.Getpid(), err) } else { return len(fds) } return -1 }
// Cleanup aufs and unmount all mountpoints func (a *Driver) Cleanup() error { for id, m := range a.active { if err := a.unmount(m); err != nil { logrus.Errorf("Unmounting %s: %s", stringid.TruncateID(id), err) } } return mountpk.Unmount(a.root) }
func getLoopbackBackingFile(file *os.File) (uint64, uint64, error) { loopInfo, err := ioctlLoopGetStatus64(file.Fd()) if err != nil { log.Errorf("Error get loopback backing file: %s", err) return 0, 0, ErrGetLoopbackBackingFile } return loopInfo.loDevice, loopInfo.loInode, nil }
func GetBlockDeviceSize(file *os.File) (uint64, error) { size, err := ioctlBlkGetSize64(file.Fd()) if err != nil { log.Errorf("Error getblockdevicesize: %s", err) return 0, ErrGetBlockSize } return uint64(size), nil }
// Matches returns true if relFilePath matches any of the patterns func Matches(relFilePath string, patterns []string) (bool, error) { for _, exclude := range patterns { matched, err := filepath.Match(exclude, relFilePath) if err != nil { log.Errorf("Error matching: %s (pattern: %s)", relFilePath, exclude) return false, err } if matched { if filepath.Clean(relFilePath) == "." { log.Errorf("Can't exclude whole path, excluding pattern: %s", exclude) continue } log.Debugf("Skipping excluded path: %s", relFilePath) return true, nil } } return false, nil }
func Unmount(target string) error { if err := exec.Command("auplink", target, "flush").Run(); err != nil { log.Errorf("Couldn't run auplink before unmount: %s", err) } if err := syscall.Unmount(target, 0); err != nil { return err } return nil }
// GetDriver initializes and returns the registered driver func GetDriver(name, home string, options []string, uidMaps, gidMaps []idtools.IDMap) (Driver, error) { if initFunc, exists := drivers[name]; exists { return initFunc(filepath.Join(home, name), options, uidMaps, gidMaps) } if pluginDriver, err := lookupPlugin(name, home, options); err == nil { return pluginDriver, nil } logrus.Errorf("Failed to GetDriver graph %s %s", name, home) return nil, ErrNotSupported }
func (msl *manifestServiceListener) GetByTag(tag string, options ...distribution.ManifestServiceOption) (*manifest.SignedManifest, error) { sm, err := msl.ManifestService.GetByTag(tag, options...) if err == nil { if err := msl.parent.listener.ManifestPulled(msl.parent.Repository.Name(), sm); err != nil { logrus.Errorf("error dispatching manifest pull to listener: %v", err) } } return sm, err }
// attachLoopDevice attaches the given sparse file to the next // available loopback device. It returns an opened *os.File. func AttachLoopDevice(sparseName string) (loop *os.File, err error) { // Try to retrieve the next available loopback device via syscall. // If it fails, we discard error and start loopking for a // loopback from index 0. startIndex, err := getNextFreeLoopbackIndex() if err != nil { log.Debugf("Error retrieving the next available loopback: %s", err) } // OpenFile adds O_CLOEXEC sparseFile, err := os.OpenFile(sparseName, os.O_RDWR, 0644) if err != nil { log.Errorf("Error opening sparse file %s: %s", sparseName, err) return nil, ErrAttachLoopbackDevice } defer sparseFile.Close() loopFile, err := openNextAvailableLoopback(startIndex, sparseFile) if err != nil { return nil, err } // Set the status of the loopback device loopInfo := &LoopInfo64{ loFileName: stringToLoopName(loopFile.Name()), loOffset: 0, loFlags: LoFlagsAutoClear, } if err := ioctlLoopSetStatus64(loopFile.Fd(), loopInfo); err != nil { log.Errorf("Cannot set up loopback device info: %s", err) // If the call failed, then free the loopback device if err := ioctlLoopClrFd(loopFile.Fd()); err != nil { log.Errorf("Error while cleaning up the loopback device") } loopFile.Close() return nil, ErrAttachLoopbackDevice } return loopFile, nil }
func (msl *manifestServiceListener) Get(dgst digest.Digest) (*manifest.SignedManifest, error) { sm, err := msl.ManifestService.Get(dgst) if err == nil { if err := msl.parent.listener.ManifestPulled(msl.parent.Repository.Name(), sm); err != nil { logrus.Errorf("error dispatching manifest pull to listener: %v", err) } } return sm, err }
// SendFile calls the specified method, and passes through the IO stream func (c *Client) SendFile(serviceMethod string, data io.Reader, ret interface{}) error { body, err := c.callWithRetry(serviceMethod, data, true) if err != nil { return err } if err := json.NewDecoder(body).Decode(&ret); err != nil { logrus.Errorf("%s: error reading plugin resp: %v", serviceMethod, err) return err } return nil }
func (msl *manifestServiceListener) Put(sm *manifest.SignedManifest) error { err := msl.ManifestService.Put(sm) if err == nil { if err := msl.parent.listener.ManifestPushed(msl.parent.Repository.Name(), sm); err != nil { logrus.Errorf("error dispatching manifest push to listener: %v", err) } } return err }
// lookupImageOnEndpoint checks the specified endpoint to see if an image exists // and if it is absent then it sends the image id to the channel to be pushed. func (p *v1Pusher) lookupImageOnEndpoint(wg *sync.WaitGroup, images chan imagePushData, imagesToPush chan string) { defer wg.Done() for image := range images { if err := p.session.LookupRemoteImage(image.compatibilityID, image.endpoint); err != nil { logrus.Errorf("Error in LookupRemoteImage: %s", err) imagesToPush <- image.id continue } p.out.Write(p.sf.FormatStatus("", "Image %s already pushed, skipping", stringid.TruncateID(image.id))) } }
// 'docker version': show version information func (cli *DockerCli) CmdVersion(args ...string) error { cmd := cli.Subcmd("version", "", "Show the Docker version information.", true) cmd.Require(flag.Exact, 0) utils.ParseFlags(cmd, args, false) if dockerversion.VERSION != "" { fmt.Fprintf(cli.out, "Client version: %s\n", dockerversion.VERSION) } fmt.Fprintf(cli.out, "Client API version: %s\n", api.APIVERSION) fmt.Fprintf(cli.out, "Go version (client): %s\n", runtime.Version()) if dockerversion.GITCOMMIT != "" { fmt.Fprintf(cli.out, "Git commit (client): %s\n", dockerversion.GITCOMMIT) } fmt.Fprintf(cli.out, "OS/Arch (client): %s/%s\n", runtime.GOOS, runtime.GOARCH) body, _, err := readBody(cli.call("GET", "/version", nil, false)) if err != nil { return err } out := engine.NewOutput() remoteVersion, err := out.AddEnv() if err != nil { log.Errorf("Error reading remote version: %s", err) return err } if _, err := out.Write(body); err != nil { log.Errorf("Error reading remote version: %s", err) return err } out.Close() fmt.Fprintf(cli.out, "Server version: %s\n", remoteVersion.Get("Version")) if apiVersion := remoteVersion.Get("ApiVersion"); apiVersion != "" { fmt.Fprintf(cli.out, "Server API version: %s\n", apiVersion) } fmt.Fprintf(cli.out, "Go version (server): %s\n", remoteVersion.Get("GoVersion")) fmt.Fprintf(cli.out, "Git commit (server): %s\n", remoteVersion.Get("GitCommit")) fmt.Fprintf(cli.out, "OS/Arch (server): %s/%s\n", remoteVersion.Get("Os"), remoteVersion.Get("Arch")) return nil }
// lookupImageOnEndpoint checks the specified endpoint to see if an image exists // and if it is absent then it sends the image id to the channel to be pushed. func lookupImageOnEndpoint(wg *sync.WaitGroup, r *registry.Session, out io.Writer, sf *utils.StreamFormatter, images chan imagePushData, imagesToPush chan string) { defer wg.Done() for image := range images { if err := r.LookupRemoteImage(image.id, image.endpoint, image.tokens); err != nil { log.Errorf("Error in LookupRemoteImage: %s", err) imagesToPush <- image.id continue } out.Write(sf.FormatStatus("", "Image %s already pushed, skipping", stringid.TruncateID(image.id))) } }
// Converts a 4 bytes IP into a 128 bit integer func ipToBigInt(ip net.IP) *big.Int { x := big.NewInt(0) if ip4 := ip.To4(); ip4 != nil { return x.SetBytes(ip4) } if ip6 := ip.To16(); ip6 != nil { return x.SetBytes(ip6) } logrus.Errorf("ipToBigInt: Wrong IP length! %s", ip) return nil }