func (daemon *Daemon) ContainerRestart(job *engine.Job) engine.Status { if len(job.Args) != 1 { return job.Errorf("Usage: %s CONTAINER\n", job.Name) } var ( name = job.Args[0] t = 10 ) if job.EnvExists("t") { t = job.GetenvInt("t") } if container := daemon.Get(name); container != nil { if err := container.Restart(int(t)); err != nil { return job.Errorf("Cannot restart container %s: %s\n", name, err) } container.LogEvent("restart") } else { return job.Errorf("No such container: %s\n", name) } return engine.StatusOK }
func (daemon *Daemon) ContainerStop(job *engine.Job) engine.Status { if len(job.Args) != 1 { return job.Errorf("Usage: %s CONTAINER\n", job.Name) } var ( name = job.Args[0] t = 10 ) if job.EnvExists("t") { t = job.GetenvInt("t") } if container := daemon.Get(name); container != nil { if !container.State.IsRunning() { return job.Errorf("Container already stopped") } if err := container.Stop(int(t)); err != nil { return job.Errorf("Cannot stop container %s: %s\n", name, err) } container.LogEvent("stop") } else { return job.Errorf("No such container: %s\n", name) } return engine.StatusOK }
// Allocate an external port and map it to the interface func AllocatePort(job *engine.Job) engine.Status { var ( err error ip = defaultBindingIP id = job.Args[0] hostIP = job.Getenv("HostIP") hostPort = job.GetenvInt("HostPort") containerPort = job.GetenvInt("ContainerPort") proto = job.Getenv("Proto") network = currentInterfaces.Get(id) ) if hostIP != "" { ip = net.ParseIP(hostIP) } // host ip, proto, and host port var container net.Addr switch proto { case "tcp": container = &net.TCPAddr{IP: network.IP, Port: containerPort} case "udp": container = &net.UDPAddr{IP: network.IP, Port: containerPort} default: return job.Errorf("unsupported address type %s", proto) } // // Try up to 10 times to get a port that's not already allocated. // // In the event of failure to bind, return the error that portmapper.Map // yields. // var host net.Addr for i := 0; i < MaxAllocatedPortAttempts; i++ { if host, err = portmapper.Map(container, ip, hostPort); err == nil { break } if allocerr, ok := err.(portallocator.ErrPortAlreadyAllocated); ok { // There is no point in immediately retrying to map an explicitly // chosen port. if hostPort != 0 { job.Logf("Failed to bind %s for container address %s: %s", allocerr.IPPort(), container.String(), allocerr.Error()) break } // Automatically chosen 'free' port failed to bind: move on the next. job.Logf("Failed to bind %s for container address %s. Trying another port.", allocerr.IPPort(), container.String()) } else { // some other error during mapping job.Logf("Received an unexpected error during port allocation: %s", err.Error()) break } } if err != nil { return job.Error(err) } network.PortMappings = append(network.PortMappings, host) out := engine.Env{} switch netAddr := host.(type) { case *net.TCPAddr: out.Set("HostIP", netAddr.IP.String()) out.SetInt("HostPort", netAddr.Port) case *net.UDPAddr: out.Set("HostIP", netAddr.IP.String()) out.SetInt("HostPort", netAddr.Port) } if _, err := out.WriteTo(job.Stdout); err != nil { return job.Error(err) } return engine.StatusOK }
func (daemon *Daemon) Containers(job *engine.Job) engine.Status { var ( foundBefore bool displayed int all = job.GetenvBool("all") since = job.Getenv("since") before = job.Getenv("before") n = job.GetenvInt("limit") size = job.GetenvBool("size") psFilters filters.Args filt_exited []int ) outs := engine.NewTable("Created", 0) psFilters, err := filters.FromParam(job.Getenv("filters")) if err != nil { return job.Error(err) } if i, ok := psFilters["exited"]; ok { for _, value := range i { code, err := strconv.Atoi(value) if err != nil { return job.Error(err) } filt_exited = append(filt_exited, code) } } names := map[string][]string{} daemon.ContainerGraph().Walk("/", func(p string, e *graphdb.Entity) error { names[e.ID()] = append(names[e.ID()], p) return nil }, -1) var beforeCont, sinceCont *Container if before != "" { beforeCont = daemon.Get(before) if beforeCont == nil { return job.Error(fmt.Errorf("Could not find container with name or id %s", before)) } } if since != "" { sinceCont = daemon.Get(since) if sinceCont == nil { return job.Error(fmt.Errorf("Could not find container with name or id %s", since)) } } errLast := errors.New("last container") writeCont := func(container *Container) error { container.Lock() defer container.Unlock() if !container.State.IsRunning() && !all && n <= 0 && since == "" && before == "" { return nil } if before != "" && !foundBefore { if container.ID == beforeCont.ID { foundBefore = true } return nil } if n > 0 && displayed == n { return errLast } if since != "" { if container.ID == sinceCont.ID { return errLast } } if len(filt_exited) > 0 && !container.State.IsRunning() { should_skip := true for _, code := range filt_exited { if code == container.State.GetExitCode() { should_skip = false break } } if should_skip { return nil } } displayed++ out := &engine.Env{} out.Set("Id", container.ID) out.SetList("Names", names[container.ID]) out.Set("Image", daemon.Repositories().ImageName(container.Image)) if len(container.Args) > 0 { args := []string{} for _, arg := range container.Args { if strings.Contains(arg, " ") { args = append(args, fmt.Sprintf("'%s'", arg)) } else { args = append(args, arg) } } argsAsString := strings.Join(args, " ") out.Set("Command", fmt.Sprintf("\"%s %s\"", container.Path, argsAsString)) } else { out.Set("Command", fmt.Sprintf("\"%s\"", container.Path)) } out.SetInt64("Created", container.Created.Unix()) out.Set("Status", container.State.String()) str, err := container.NetworkSettings.PortMappingAPI().ToListString() if err != nil { return err } out.Set("Ports", str) if size { sizeRw, sizeRootFs := container.GetSize() out.SetInt64("SizeRw", sizeRw) out.SetInt64("SizeRootFs", sizeRootFs) } outs.Add(out) return nil } for _, container := range daemon.List() { if err := writeCont(container); err != nil { if err != errLast { return job.Error(err) } break } } outs.ReverseSort() if _, err := outs.WriteListTo(job.Stdout); err != nil { return job.Error(err) } return engine.StatusOK }