mirror of https://github.com/docker/docs.git
				
				
				
			Move some container related methods and structs to smaller files
Signed-off-by: Vincent Demeester <vincent@sbr.pm>
This commit is contained in:
		
							parent
							
								
									ce07eac570
								
							
						
					
					
						commit
						fb48bf518b
					
				|  | @ -11,5 +11,5 @@ func (daemon *Daemon) ContainerChanges(name string) ([]archive.Change, error) { | |||
| 
 | ||||
| 	container.Lock() | ||||
| 	defer container.Unlock() | ||||
| 	return daemon.changes(container) | ||||
| 	return container.RWLayer.Changes() | ||||
| } | ||||
|  |  | |||
|  | @ -0,0 +1,145 @@ | |||
| package daemon | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"path/filepath" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/docker/docker/container" | ||||
| 	"github.com/docker/docker/daemon/network" | ||||
| 	"github.com/docker/docker/errors" | ||||
| 	"github.com/docker/docker/image" | ||||
| 	"github.com/docker/docker/pkg/truncindex" | ||||
| 	containertypes "github.com/docker/engine-api/types/container" | ||||
| ) | ||||
| 
 | ||||
| // GetContainer looks for a container using the provided information, which could be
 | ||||
| // one of the following inputs from the caller:
 | ||||
| //  - A full container ID, which will exact match a container in daemon's list
 | ||||
| //  - A container name, which will only exact match via the GetByName() function
 | ||||
| //  - A partial container ID prefix (e.g. short ID) of any length that is
 | ||||
| //    unique enough to only return a single container object
 | ||||
| //  If none of these searches succeed, an error is returned
 | ||||
| func (daemon *Daemon) GetContainer(prefixOrName string) (*container.Container, error) { | ||||
| 	if len(prefixOrName) == 0 { | ||||
| 		return nil, errors.NewBadRequestError(fmt.Errorf("No container name or ID supplied")) | ||||
| 	} | ||||
| 
 | ||||
| 	if containerByID := daemon.containers.Get(prefixOrName); containerByID != nil { | ||||
| 		// prefix is an exact match to a full container ID
 | ||||
| 		return containerByID, nil | ||||
| 	} | ||||
| 
 | ||||
| 	// GetByName will match only an exact name provided; we ignore errors
 | ||||
| 	if containerByName, _ := daemon.GetByName(prefixOrName); containerByName != nil { | ||||
| 		// prefix is an exact match to a full container Name
 | ||||
| 		return containerByName, nil | ||||
| 	} | ||||
| 
 | ||||
| 	containerID, indexError := daemon.idIndex.Get(prefixOrName) | ||||
| 	if indexError != nil { | ||||
| 		// When truncindex defines an error type, use that instead
 | ||||
| 		if indexError == truncindex.ErrNotExist { | ||||
| 			err := fmt.Errorf("No such container: %s", prefixOrName) | ||||
| 			return nil, errors.NewRequestNotFoundError(err) | ||||
| 		} | ||||
| 		return nil, indexError | ||||
| 	} | ||||
| 	return daemon.containers.Get(containerID), nil | ||||
| } | ||||
| 
 | ||||
| // Exists returns a true if a container of the specified ID or name exists,
 | ||||
| // false otherwise.
 | ||||
| func (daemon *Daemon) Exists(id string) bool { | ||||
| 	c, _ := daemon.GetContainer(id) | ||||
| 	return c != nil | ||||
| } | ||||
| 
 | ||||
| // IsPaused returns a bool indicating if the specified container is paused.
 | ||||
| func (daemon *Daemon) IsPaused(id string) bool { | ||||
| 	c, _ := daemon.GetContainer(id) | ||||
| 	return c.State.IsPaused() | ||||
| } | ||||
| 
 | ||||
| func (daemon *Daemon) containerRoot(id string) string { | ||||
| 	return filepath.Join(daemon.repository, id) | ||||
| } | ||||
| 
 | ||||
| // Load reads the contents of a container from disk
 | ||||
| // This is typically done at startup.
 | ||||
| func (daemon *Daemon) load(id string) (*container.Container, error) { | ||||
| 	container := daemon.newBaseContainer(id) | ||||
| 
 | ||||
| 	if err := container.FromDisk(); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	if container.ID != id { | ||||
| 		return container, fmt.Errorf("Container %s is stored at %s", container.ID, id) | ||||
| 	} | ||||
| 
 | ||||
| 	return container, nil | ||||
| } | ||||
| 
 | ||||
| // Register makes a container object usable by the daemon as <container.ID>
 | ||||
| func (daemon *Daemon) Register(c *container.Container) error { | ||||
| 	// Attach to stdout and stderr
 | ||||
| 	if c.Config.OpenStdin { | ||||
| 		c.NewInputPipes() | ||||
| 	} else { | ||||
| 		c.NewNopInputPipe() | ||||
| 	} | ||||
| 
 | ||||
| 	daemon.containers.Add(c.ID, c) | ||||
| 	daemon.idIndex.Add(c.ID) | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (daemon *Daemon) newContainer(name string, config *containertypes.Config, imgID image.ID) (*container.Container, error) { | ||||
| 	var ( | ||||
| 		id             string | ||||
| 		err            error | ||||
| 		noExplicitName = name == "" | ||||
| 	) | ||||
| 	id, name, err = daemon.generateIDAndName(name) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	daemon.generateHostname(id, config) | ||||
| 	entrypoint, args := daemon.getEntrypointAndArgs(config.Entrypoint, config.Cmd) | ||||
| 
 | ||||
| 	base := daemon.newBaseContainer(id) | ||||
| 	base.Created = time.Now().UTC() | ||||
| 	base.Path = entrypoint | ||||
| 	base.Args = args //FIXME: de-duplicate from config
 | ||||
| 	base.Config = config | ||||
| 	base.HostConfig = &containertypes.HostConfig{} | ||||
| 	base.ImageID = imgID | ||||
| 	base.NetworkSettings = &network.Settings{IsAnonymousEndpoint: noExplicitName} | ||||
| 	base.Name = name | ||||
| 	base.Driver = daemon.GraphDriverName() | ||||
| 
 | ||||
| 	return base, err | ||||
| } | ||||
| 
 | ||||
| // GetByName returns a container given a name.
 | ||||
| func (daemon *Daemon) GetByName(name string) (*container.Container, error) { | ||||
| 	if len(name) == 0 { | ||||
| 		return nil, fmt.Errorf("No container name supplied") | ||||
| 	} | ||||
| 	fullName := name | ||||
| 	if name[0] != '/' { | ||||
| 		fullName = "/" + name | ||||
| 	} | ||||
| 	id, err := daemon.nameIndex.Get(fullName) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("Could not find entity for %s", name) | ||||
| 	} | ||||
| 	e := daemon.containers.Get(id) | ||||
| 	if e == nil { | ||||
| 		return nil, fmt.Errorf("Could not find container for entity id %s", id) | ||||
| 	} | ||||
| 	return e, nil | ||||
| } | ||||
|  | @ -218,3 +218,15 @@ func (daemon *Daemon) VolumeCreate(name, driverName string, opts, labels map[str | |||
| 	apiV.Mountpoint = v.Path() | ||||
| 	return apiV, nil | ||||
| } | ||||
| 
 | ||||
| func (daemon *Daemon) mergeAndVerifyConfig(config *containertypes.Config, img *image.Image) error { | ||||
| 	if img != nil && img.Config != nil { | ||||
| 		if err := merge(config, img.Config); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	if len(config.Entrypoint) == 0 && len(config.Cmd) == 0 { | ||||
| 		return fmt.Errorf("No command specified") | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  |  | |||
							
								
								
									
										257
									
								
								daemon/daemon.go
								
								
								
								
							
							
						
						
									
										257
									
								
								daemon/daemon.go
								
								
								
								
							|  | @ -36,7 +36,6 @@ import ( | |||
| 	"github.com/docker/engine-api/types/strslice" | ||||
| 	// register graph drivers
 | ||||
| 	_ "github.com/docker/docker/daemon/graphdriver/register" | ||||
| 	"github.com/docker/docker/daemon/network" | ||||
| 	dmetadata "github.com/docker/docker/distribution/metadata" | ||||
| 	"github.com/docker/docker/distribution/xfer" | ||||
| 	"github.com/docker/docker/dockerversion" | ||||
|  | @ -44,16 +43,13 @@ import ( | |||
| 	"github.com/docker/docker/layer" | ||||
| 	"github.com/docker/docker/libcontainerd" | ||||
| 	"github.com/docker/docker/migrate/v1" | ||||
| 	"github.com/docker/docker/pkg/archive" | ||||
| 	"github.com/docker/docker/pkg/fileutils" | ||||
| 	"github.com/docker/docker/pkg/graphdb" | ||||
| 	"github.com/docker/docker/pkg/idtools" | ||||
| 	"github.com/docker/docker/pkg/namesgenerator" | ||||
| 	"github.com/docker/docker/pkg/progress" | ||||
| 	"github.com/docker/docker/pkg/registrar" | ||||
| 	"github.com/docker/docker/pkg/signal" | ||||
| 	"github.com/docker/docker/pkg/streamformatter" | ||||
| 	"github.com/docker/docker/pkg/stringid" | ||||
| 	"github.com/docker/docker/pkg/sysinfo" | ||||
| 	"github.com/docker/docker/pkg/system" | ||||
| 	"github.com/docker/docker/pkg/truncindex" | ||||
|  | @ -73,9 +69,6 @@ import ( | |||
| ) | ||||
| 
 | ||||
| var ( | ||||
| 	validContainerNameChars   = utils.RestrictedNameChars | ||||
| 	validContainerNamePattern = utils.RestrictedNamePattern | ||||
| 
 | ||||
| 	errSystemNotSupported = fmt.Errorf("The Docker daemon is not supported on this platform.") | ||||
| ) | ||||
| 
 | ||||
|  | @ -112,110 +105,6 @@ type Daemon struct { | |||
| 	defaultIsolation          containertypes.Isolation // Default isolation mode on Windows
 | ||||
| } | ||||
| 
 | ||||
| // GetContainer looks for a container using the provided information, which could be
 | ||||
| // one of the following inputs from the caller:
 | ||||
| //  - A full container ID, which will exact match a container in daemon's list
 | ||||
| //  - A container name, which will only exact match via the GetByName() function
 | ||||
| //  - A partial container ID prefix (e.g. short ID) of any length that is
 | ||||
| //    unique enough to only return a single container object
 | ||||
| //  If none of these searches succeed, an error is returned
 | ||||
| func (daemon *Daemon) GetContainer(prefixOrName string) (*container.Container, error) { | ||||
| 	if len(prefixOrName) == 0 { | ||||
| 		return nil, errors.NewBadRequestError(fmt.Errorf("No container name or ID supplied")) | ||||
| 	} | ||||
| 
 | ||||
| 	if containerByID := daemon.containers.Get(prefixOrName); containerByID != nil { | ||||
| 		// prefix is an exact match to a full container ID
 | ||||
| 		return containerByID, nil | ||||
| 	} | ||||
| 
 | ||||
| 	// GetByName will match only an exact name provided; we ignore errors
 | ||||
| 	if containerByName, _ := daemon.GetByName(prefixOrName); containerByName != nil { | ||||
| 		// prefix is an exact match to a full container Name
 | ||||
| 		return containerByName, nil | ||||
| 	} | ||||
| 
 | ||||
| 	containerID, indexError := daemon.idIndex.Get(prefixOrName) | ||||
| 	if indexError != nil { | ||||
| 		// When truncindex defines an error type, use that instead
 | ||||
| 		if indexError == truncindex.ErrNotExist { | ||||
| 			err := fmt.Errorf("No such container: %s", prefixOrName) | ||||
| 			return nil, errors.NewRequestNotFoundError(err) | ||||
| 		} | ||||
| 		return nil, indexError | ||||
| 	} | ||||
| 	return daemon.containers.Get(containerID), nil | ||||
| } | ||||
| 
 | ||||
| // Exists returns a true if a container of the specified ID or name exists,
 | ||||
| // false otherwise.
 | ||||
| func (daemon *Daemon) Exists(id string) bool { | ||||
| 	c, _ := daemon.GetContainer(id) | ||||
| 	return c != nil | ||||
| } | ||||
| 
 | ||||
| // IsPaused returns a bool indicating if the specified container is paused.
 | ||||
| func (daemon *Daemon) IsPaused(id string) bool { | ||||
| 	c, _ := daemon.GetContainer(id) | ||||
| 	return c.State.IsPaused() | ||||
| } | ||||
| 
 | ||||
| func (daemon *Daemon) containerRoot(id string) string { | ||||
| 	return filepath.Join(daemon.repository, id) | ||||
| } | ||||
| 
 | ||||
| // Load reads the contents of a container from disk
 | ||||
| // This is typically done at startup.
 | ||||
| func (daemon *Daemon) load(id string) (*container.Container, error) { | ||||
| 	container := daemon.newBaseContainer(id) | ||||
| 
 | ||||
| 	if err := container.FromDisk(); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	if container.ID != id { | ||||
| 		return container, fmt.Errorf("Container %s is stored at %s", container.ID, id) | ||||
| 	} | ||||
| 
 | ||||
| 	return container, nil | ||||
| } | ||||
| 
 | ||||
| func (daemon *Daemon) registerName(container *container.Container) error { | ||||
| 	if daemon.Exists(container.ID) { | ||||
| 		return fmt.Errorf("Container is already loaded") | ||||
| 	} | ||||
| 	if err := validateID(container.ID); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if container.Name == "" { | ||||
| 		name, err := daemon.generateNewName(container.ID) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		container.Name = name | ||||
| 
 | ||||
| 		if err := container.ToDiskLocking(); err != nil { | ||||
| 			logrus.Errorf("Error saving container name to disk: %v", err) | ||||
| 		} | ||||
| 	} | ||||
| 	return daemon.nameIndex.Reserve(container.Name, container.ID) | ||||
| } | ||||
| 
 | ||||
| // Register makes a container object usable by the daemon as <container.ID>
 | ||||
| func (daemon *Daemon) Register(c *container.Container) error { | ||||
| 	// Attach to stdout and stderr
 | ||||
| 	if c.Config.OpenStdin { | ||||
| 		c.NewInputPipes() | ||||
| 	} else { | ||||
| 		c.NewNopInputPipe() | ||||
| 	} | ||||
| 
 | ||||
| 	daemon.containers.Add(c.ID, c) | ||||
| 	daemon.idIndex.Add(c.ID) | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (daemon *Daemon) restore() error { | ||||
| 	var ( | ||||
| 		debug         = utils.IsDebugEnabled() | ||||
|  | @ -431,88 +320,6 @@ func (daemon *Daemon) waitForNetworks(c *container.Container) { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (daemon *Daemon) mergeAndVerifyConfig(config *containertypes.Config, img *image.Image) error { | ||||
| 	if img != nil && img.Config != nil { | ||||
| 		if err := merge(config, img.Config); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	if len(config.Entrypoint) == 0 && len(config.Cmd) == 0 { | ||||
| 		return fmt.Errorf("No command specified") | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (daemon *Daemon) generateIDAndName(name string) (string, string, error) { | ||||
| 	var ( | ||||
| 		err error | ||||
| 		id  = stringid.GenerateNonCryptoID() | ||||
| 	) | ||||
| 
 | ||||
| 	if name == "" { | ||||
| 		if name, err = daemon.generateNewName(id); err != nil { | ||||
| 			return "", "", err | ||||
| 		} | ||||
| 		return id, name, nil | ||||
| 	} | ||||
| 
 | ||||
| 	if name, err = daemon.reserveName(id, name); err != nil { | ||||
| 		return "", "", err | ||||
| 	} | ||||
| 
 | ||||
| 	return id, name, nil | ||||
| } | ||||
| 
 | ||||
| func (daemon *Daemon) reserveName(id, name string) (string, error) { | ||||
| 	if !validContainerNamePattern.MatchString(name) { | ||||
| 		return "", fmt.Errorf("Invalid container name (%s), only %s are allowed", name, validContainerNameChars) | ||||
| 	} | ||||
| 	if name[0] != '/' { | ||||
| 		name = "/" + name | ||||
| 	} | ||||
| 
 | ||||
| 	if err := daemon.nameIndex.Reserve(name, id); err != nil { | ||||
| 		if err == registrar.ErrNameReserved { | ||||
| 			id, err := daemon.nameIndex.Get(name) | ||||
| 			if err != nil { | ||||
| 				logrus.Errorf("got unexpected error while looking up reserved name: %v", err) | ||||
| 				return "", err | ||||
| 			} | ||||
| 			return "", fmt.Errorf("Conflict. The name %q is already in use by container %s. You have to remove (or rename) that container to be able to reuse that name.", name, id) | ||||
| 		} | ||||
| 		return "", fmt.Errorf("error reserving name: %s, error: %v", name, err) | ||||
| 	} | ||||
| 	return name, nil | ||||
| } | ||||
| 
 | ||||
| func (daemon *Daemon) releaseName(name string) { | ||||
| 	daemon.nameIndex.Release(name) | ||||
| } | ||||
| 
 | ||||
| func (daemon *Daemon) generateNewName(id string) (string, error) { | ||||
| 	var name string | ||||
| 	for i := 0; i < 6; i++ { | ||||
| 		name = namesgenerator.GetRandomName(i) | ||||
| 		if name[0] != '/' { | ||||
| 			name = "/" + name | ||||
| 		} | ||||
| 
 | ||||
| 		if err := daemon.nameIndex.Reserve(name, id); err != nil { | ||||
| 			if err == registrar.ErrNameReserved { | ||||
| 				continue | ||||
| 			} | ||||
| 			return "", err | ||||
| 		} | ||||
| 		return name, nil | ||||
| 	} | ||||
| 
 | ||||
| 	name = "/" + stringid.TruncateID(id) | ||||
| 	if err := daemon.nameIndex.Reserve(name, id); err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	return name, nil | ||||
| } | ||||
| 
 | ||||
| func (daemon *Daemon) generateHostname(id string, config *containertypes.Config) { | ||||
| 	// Generate default hostname
 | ||||
| 	if config.Hostname == "" { | ||||
|  | @ -527,54 +334,6 @@ func (daemon *Daemon) getEntrypointAndArgs(configEntrypoint strslice.StrSlice, c | |||
| 	return configCmd[0], configCmd[1:] | ||||
| } | ||||
| 
 | ||||
| func (daemon *Daemon) newContainer(name string, config *containertypes.Config, imgID image.ID) (*container.Container, error) { | ||||
| 	var ( | ||||
| 		id             string | ||||
| 		err            error | ||||
| 		noExplicitName = name == "" | ||||
| 	) | ||||
| 	id, name, err = daemon.generateIDAndName(name) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	daemon.generateHostname(id, config) | ||||
| 	entrypoint, args := daemon.getEntrypointAndArgs(config.Entrypoint, config.Cmd) | ||||
| 
 | ||||
| 	base := daemon.newBaseContainer(id) | ||||
| 	base.Created = time.Now().UTC() | ||||
| 	base.Path = entrypoint | ||||
| 	base.Args = args //FIXME: de-duplicate from config
 | ||||
| 	base.Config = config | ||||
| 	base.HostConfig = &containertypes.HostConfig{} | ||||
| 	base.ImageID = imgID | ||||
| 	base.NetworkSettings = &network.Settings{IsAnonymousEndpoint: noExplicitName} | ||||
| 	base.Name = name | ||||
| 	base.Driver = daemon.GraphDriverName() | ||||
| 
 | ||||
| 	return base, err | ||||
| } | ||||
| 
 | ||||
| // GetByName returns a container given a name.
 | ||||
| func (daemon *Daemon) GetByName(name string) (*container.Container, error) { | ||||
| 	if len(name) == 0 { | ||||
| 		return nil, fmt.Errorf("No container name supplied") | ||||
| 	} | ||||
| 	fullName := name | ||||
| 	if name[0] != '/' { | ||||
| 		fullName = "/" + name | ||||
| 	} | ||||
| 	id, err := daemon.nameIndex.Get(fullName) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("Could not find entity for %s", name) | ||||
| 	} | ||||
| 	e := daemon.containers.Get(id) | ||||
| 	if e == nil { | ||||
| 		return nil, fmt.Errorf("Could not find container for entity id %s", id) | ||||
| 	} | ||||
| 	return e, nil | ||||
| } | ||||
| 
 | ||||
| // GetLabels for a container or image id
 | ||||
| func (daemon *Daemon) GetLabels(id string) map[string]string { | ||||
| 	// TODO: TestCase
 | ||||
|  | @ -947,22 +706,6 @@ func (daemon *Daemon) Unmount(container *container.Container) error { | |||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (daemon *Daemon) kill(c *container.Container, sig int) error { | ||||
| 	return daemon.containerd.Signal(c.ID, sig) | ||||
| } | ||||
| 
 | ||||
| func (daemon *Daemon) subscribeToContainerStats(c *container.Container) chan interface{} { | ||||
| 	return daemon.statsCollector.collect(c) | ||||
| } | ||||
| 
 | ||||
| func (daemon *Daemon) unsubscribeToContainerStats(c *container.Container, ch chan interface{}) { | ||||
| 	daemon.statsCollector.unsubscribe(c, ch) | ||||
| } | ||||
| 
 | ||||
| func (daemon *Daemon) changes(container *container.Container) ([]archive.Change, error) { | ||||
| 	return container.RWLayer.Changes() | ||||
| } | ||||
| 
 | ||||
| func writeDistributionProgress(cancelFunc func(), outStream io.Writer, progressChan <-chan progress.Progress) { | ||||
| 	progressOutput := streamformatter.NewJSONStreamFormatter().NewProgressOutput(outStream, false) | ||||
| 	operationCancelled := false | ||||
|  |  | |||
|  | @ -151,3 +151,7 @@ func (daemon *Daemon) killPossiblyDeadProcess(container *container.Container, si | |||
| 	} | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| func (daemon *Daemon) kill(c *container.Container, sig int) error { | ||||
| 	return daemon.containerd.Signal(c.ID, sig) | ||||
| } | ||||
|  |  | |||
|  | @ -0,0 +1,108 @@ | |||
| package daemon | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 
 | ||||
| 	"github.com/Sirupsen/logrus" | ||||
| 	"github.com/docker/docker/container" | ||||
| 	"github.com/docker/docker/pkg/namesgenerator" | ||||
| 	"github.com/docker/docker/pkg/registrar" | ||||
| 	"github.com/docker/docker/pkg/stringid" | ||||
| 	"github.com/docker/docker/utils" | ||||
| ) | ||||
| 
 | ||||
| var ( | ||||
| 	validContainerNameChars   = utils.RestrictedNameChars | ||||
| 	validContainerNamePattern = utils.RestrictedNamePattern | ||||
| ) | ||||
| 
 | ||||
| func (daemon *Daemon) registerName(container *container.Container) error { | ||||
| 	if daemon.Exists(container.ID) { | ||||
| 		return fmt.Errorf("Container is already loaded") | ||||
| 	} | ||||
| 	if err := validateID(container.ID); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if container.Name == "" { | ||||
| 		name, err := daemon.generateNewName(container.ID) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		container.Name = name | ||||
| 
 | ||||
| 		if err := container.ToDiskLocking(); err != nil { | ||||
| 			logrus.Errorf("Error saving container name to disk: %v", err) | ||||
| 		} | ||||
| 	} | ||||
| 	return daemon.nameIndex.Reserve(container.Name, container.ID) | ||||
| } | ||||
| 
 | ||||
| func (daemon *Daemon) generateIDAndName(name string) (string, string, error) { | ||||
| 	var ( | ||||
| 		err error | ||||
| 		id  = stringid.GenerateNonCryptoID() | ||||
| 	) | ||||
| 
 | ||||
| 	if name == "" { | ||||
| 		if name, err = daemon.generateNewName(id); err != nil { | ||||
| 			return "", "", err | ||||
| 		} | ||||
| 		return id, name, nil | ||||
| 	} | ||||
| 
 | ||||
| 	if name, err = daemon.reserveName(id, name); err != nil { | ||||
| 		return "", "", err | ||||
| 	} | ||||
| 
 | ||||
| 	return id, name, nil | ||||
| } | ||||
| 
 | ||||
| func (daemon *Daemon) reserveName(id, name string) (string, error) { | ||||
| 	if !validContainerNamePattern.MatchString(name) { | ||||
| 		return "", fmt.Errorf("Invalid container name (%s), only %s are allowed", name, validContainerNameChars) | ||||
| 	} | ||||
| 	if name[0] != '/' { | ||||
| 		name = "/" + name | ||||
| 	} | ||||
| 
 | ||||
| 	if err := daemon.nameIndex.Reserve(name, id); err != nil { | ||||
| 		if err == registrar.ErrNameReserved { | ||||
| 			id, err := daemon.nameIndex.Get(name) | ||||
| 			if err != nil { | ||||
| 				logrus.Errorf("got unexpected error while looking up reserved name: %v", err) | ||||
| 				return "", err | ||||
| 			} | ||||
| 			return "", fmt.Errorf("Conflict. The name %q is already in use by container %s. You have to remove (or rename) that container to be able to reuse that name.", name, id) | ||||
| 		} | ||||
| 		return "", fmt.Errorf("error reserving name: %s, error: %v", name, err) | ||||
| 	} | ||||
| 	return name, nil | ||||
| } | ||||
| 
 | ||||
| func (daemon *Daemon) releaseName(name string) { | ||||
| 	daemon.nameIndex.Release(name) | ||||
| } | ||||
| 
 | ||||
| func (daemon *Daemon) generateNewName(id string) (string, error) { | ||||
| 	var name string | ||||
| 	for i := 0; i < 6; i++ { | ||||
| 		name = namesgenerator.GetRandomName(i) | ||||
| 		if name[0] != '/' { | ||||
| 			name = "/" + name | ||||
| 		} | ||||
| 
 | ||||
| 		if err := daemon.nameIndex.Reserve(name, id); err != nil { | ||||
| 			if err == registrar.ErrNameReserved { | ||||
| 				continue | ||||
| 			} | ||||
| 			return "", err | ||||
| 		} | ||||
| 		return name, nil | ||||
| 	} | ||||
| 
 | ||||
| 	name = "/" + stringid.TruncateID(id) | ||||
| 	if err := daemon.nameIndex.Reserve(name, id); err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	return name, nil | ||||
| } | ||||
|  | @ -8,6 +8,7 @@ import ( | |||
| 	"golang.org/x/net/context" | ||||
| 
 | ||||
| 	"github.com/docker/docker/api/types/backend" | ||||
| 	"github.com/docker/docker/container" | ||||
| 	"github.com/docker/docker/pkg/ioutils" | ||||
| 	"github.com/docker/engine-api/types" | ||||
| 	"github.com/docker/engine-api/types/versions" | ||||
|  | @ -121,3 +122,11 @@ func (daemon *Daemon) ContainerStats(ctx context.Context, prefixOrName string, c | |||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (daemon *Daemon) subscribeToContainerStats(c *container.Container) chan interface{} { | ||||
| 	return daemon.statsCollector.collect(c) | ||||
| } | ||||
| 
 | ||||
| func (daemon *Daemon) unsubscribeToContainerStats(c *container.Container, ch chan interface{}) { | ||||
| 	daemon.statsCollector.unsubscribe(c, ch) | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue