mirror of https://github.com/docker/docs.git
Moving some more methods away from daemon.go
Signed-off-by: Vincent Demeester <vincent@sbr.pm>
This commit is contained in:
parent
75109b32db
commit
bfa0885c37
|
@ -0,0 +1,13 @@
|
||||||
|
package daemon
|
||||||
|
|
||||||
|
import (
|
||||||
|
"golang.org/x/net/context"
|
||||||
|
|
||||||
|
"github.com/docker/docker/dockerversion"
|
||||||
|
"github.com/docker/engine-api/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AuthenticateToRegistry checks the validity of credentials in authConfig
|
||||||
|
func (daemon *Daemon) AuthenticateToRegistry(ctx context.Context, authConfig *types.AuthConfig) (string, string, error) {
|
||||||
|
return daemon.RegistryService.Auth(ctx, authConfig, dockerversion.DockerUserAgent(ctx))
|
||||||
|
}
|
|
@ -3,14 +3,19 @@ package daemon
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/docker/docker/container"
|
"github.com/docker/docker/container"
|
||||||
"github.com/docker/docker/daemon/network"
|
"github.com/docker/docker/daemon/network"
|
||||||
"github.com/docker/docker/errors"
|
"github.com/docker/docker/errors"
|
||||||
"github.com/docker/docker/image"
|
"github.com/docker/docker/image"
|
||||||
|
"github.com/docker/docker/pkg/signal"
|
||||||
|
"github.com/docker/docker/pkg/system"
|
||||||
"github.com/docker/docker/pkg/truncindex"
|
"github.com/docker/docker/pkg/truncindex"
|
||||||
containertypes "github.com/docker/engine-api/types/container"
|
containertypes "github.com/docker/engine-api/types/container"
|
||||||
|
"github.com/docker/engine-api/types/strslice"
|
||||||
|
"github.com/docker/go-connections/nat"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetContainer looks for a container using the provided information, which could be
|
// GetContainer looks for a container using the provided information, which could be
|
||||||
|
@ -143,3 +148,108 @@ func (daemon *Daemon) GetByName(name string) (*container.Container, error) {
|
||||||
}
|
}
|
||||||
return e, nil
|
return e, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// newBaseContainer creates a new container with its initial
|
||||||
|
// configuration based on the root storage from the daemon.
|
||||||
|
func (daemon *Daemon) newBaseContainer(id string) *container.Container {
|
||||||
|
return container.NewBaseContainer(id, daemon.containerRoot(id))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (daemon *Daemon) getEntrypointAndArgs(configEntrypoint strslice.StrSlice, configCmd strslice.StrSlice) (string, []string) {
|
||||||
|
if len(configEntrypoint) != 0 {
|
||||||
|
return configEntrypoint[0], append(configEntrypoint[1:], configCmd...)
|
||||||
|
}
|
||||||
|
return configCmd[0], configCmd[1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (daemon *Daemon) generateHostname(id string, config *containertypes.Config) {
|
||||||
|
// Generate default hostname
|
||||||
|
if config.Hostname == "" {
|
||||||
|
config.Hostname = id[:12]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (daemon *Daemon) setSecurityOptions(container *container.Container, hostConfig *containertypes.HostConfig) error {
|
||||||
|
container.Lock()
|
||||||
|
defer container.Unlock()
|
||||||
|
return parseSecurityOpt(container, hostConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (daemon *Daemon) setHostConfig(container *container.Container, hostConfig *containertypes.HostConfig) error {
|
||||||
|
// Do not lock while creating volumes since this could be calling out to external plugins
|
||||||
|
// Don't want to block other actions, like `docker ps` because we're waiting on an external plugin
|
||||||
|
if err := daemon.registerMountPoints(container, hostConfig); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
container.Lock()
|
||||||
|
defer container.Unlock()
|
||||||
|
|
||||||
|
// Register any links from the host config before starting the container
|
||||||
|
if err := daemon.registerLinks(container, hostConfig); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure links is not nil
|
||||||
|
// this ensures that on the next daemon restart we don't try to migrate from legacy sqlite links
|
||||||
|
if hostConfig.Links == nil {
|
||||||
|
hostConfig.Links = []string{}
|
||||||
|
}
|
||||||
|
|
||||||
|
container.HostConfig = hostConfig
|
||||||
|
return container.ToDisk()
|
||||||
|
}
|
||||||
|
|
||||||
|
// verifyContainerSettings performs validation of the hostconfig and config
|
||||||
|
// structures.
|
||||||
|
func (daemon *Daemon) verifyContainerSettings(hostConfig *containertypes.HostConfig, config *containertypes.Config, update bool) ([]string, error) {
|
||||||
|
|
||||||
|
// First perform verification of settings common across all platforms.
|
||||||
|
if config != nil {
|
||||||
|
if config.WorkingDir != "" {
|
||||||
|
config.WorkingDir = filepath.FromSlash(config.WorkingDir) // Ensure in platform semantics
|
||||||
|
if !system.IsAbs(config.WorkingDir) {
|
||||||
|
return nil, fmt.Errorf("The working directory '%s' is invalid. It needs to be an absolute path", config.WorkingDir)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(config.StopSignal) > 0 {
|
||||||
|
_, err := signal.ParseSignal(config.StopSignal)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate if the given hostname is RFC 1123 (https://tools.ietf.org/html/rfc1123) compliant.
|
||||||
|
if len(config.Hostname) > 0 {
|
||||||
|
// RFC1123 specifies that 63 bytes is the maximium length
|
||||||
|
// Windows has the limitation of 63 bytes in length
|
||||||
|
// Linux hostname is limited to HOST_NAME_MAX=64, not not including the terminating null byte.
|
||||||
|
// We limit the length to 63 bytes here to match RFC1035 and RFC1123.
|
||||||
|
matched, _ := regexp.MatchString("^(([[:alnum:]]|[[:alnum:]][[:alnum:]\\-]*[[:alnum:]])\\.)*([[:alnum:]]|[[:alnum:]][[:alnum:]\\-]*[[:alnum:]])$", config.Hostname)
|
||||||
|
if len(config.Hostname) > 63 || !matched {
|
||||||
|
return nil, fmt.Errorf("invalid hostname format: %s", config.Hostname)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if hostConfig == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for port := range hostConfig.PortBindings {
|
||||||
|
_, portStr := nat.SplitProtoPort(string(port))
|
||||||
|
if _, err := nat.ParsePort(portStr); err != nil {
|
||||||
|
return nil, fmt.Errorf("Invalid port specification: %q", portStr)
|
||||||
|
}
|
||||||
|
for _, pb := range hostConfig.PortBindings[port] {
|
||||||
|
_, err := nat.NewPort(nat.SplitProtoPort(pb.HostPort))
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Invalid port specification: %q", pb.HostPort)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now do platform-specific verification
|
||||||
|
return verifyPlatformContainerSettings(daemon, hostConfig, config, update)
|
||||||
|
}
|
||||||
|
|
|
@ -2,9 +2,11 @@ package daemon
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/Sirupsen/logrus"
|
"github.com/Sirupsen/logrus"
|
||||||
"github.com/docker/docker/container"
|
"github.com/docker/docker/container"
|
||||||
|
"github.com/docker/docker/errors"
|
||||||
"github.com/docker/docker/image"
|
"github.com/docker/docker/image"
|
||||||
"github.com/docker/docker/layer"
|
"github.com/docker/docker/layer"
|
||||||
"github.com/docker/docker/pkg/idtools"
|
"github.com/docker/docker/pkg/idtools"
|
||||||
|
@ -234,3 +236,16 @@ func (daemon *Daemon) mergeAndVerifyConfig(config *containertypes.Config, img *i
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Checks if the client set configurations for more than one network while creating a container
|
||||||
|
func (daemon *Daemon) verifyNetworkingConfig(nwConfig *networktypes.NetworkingConfig) error {
|
||||||
|
if nwConfig == nil || len(nwConfig.EndpointsConfig) <= 1 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
l := make([]string, 0, len(nwConfig.EndpointsConfig))
|
||||||
|
for k := range nwConfig.EndpointsConfig {
|
||||||
|
l = append(l, k)
|
||||||
|
}
|
||||||
|
err := fmt.Errorf("Container cannot be connected to network endpoints: %s", strings.Join(l, ", "))
|
||||||
|
return errors.NewBadRequestError(err)
|
||||||
|
}
|
||||||
|
|
214
daemon/daemon.go
214
daemon/daemon.go
|
@ -14,7 +14,6 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -27,16 +26,12 @@ import (
|
||||||
"github.com/docker/docker/container"
|
"github.com/docker/docker/container"
|
||||||
"github.com/docker/docker/daemon/events"
|
"github.com/docker/docker/daemon/events"
|
||||||
"github.com/docker/docker/daemon/exec"
|
"github.com/docker/docker/daemon/exec"
|
||||||
"github.com/docker/docker/errors"
|
|
||||||
"github.com/docker/engine-api/types"
|
"github.com/docker/engine-api/types"
|
||||||
containertypes "github.com/docker/engine-api/types/container"
|
containertypes "github.com/docker/engine-api/types/container"
|
||||||
networktypes "github.com/docker/engine-api/types/network"
|
|
||||||
"github.com/docker/engine-api/types/strslice"
|
|
||||||
// register graph drivers
|
// register graph drivers
|
||||||
_ "github.com/docker/docker/daemon/graphdriver/register"
|
_ "github.com/docker/docker/daemon/graphdriver/register"
|
||||||
dmetadata "github.com/docker/docker/distribution/metadata"
|
dmetadata "github.com/docker/docker/distribution/metadata"
|
||||||
"github.com/docker/docker/distribution/xfer"
|
"github.com/docker/docker/distribution/xfer"
|
||||||
"github.com/docker/docker/dockerversion"
|
|
||||||
"github.com/docker/docker/image"
|
"github.com/docker/docker/image"
|
||||||
"github.com/docker/docker/layer"
|
"github.com/docker/docker/layer"
|
||||||
"github.com/docker/docker/libcontainerd"
|
"github.com/docker/docker/libcontainerd"
|
||||||
|
@ -58,11 +53,9 @@ import (
|
||||||
volumedrivers "github.com/docker/docker/volume/drivers"
|
volumedrivers "github.com/docker/docker/volume/drivers"
|
||||||
"github.com/docker/docker/volume/local"
|
"github.com/docker/docker/volume/local"
|
||||||
"github.com/docker/docker/volume/store"
|
"github.com/docker/docker/volume/store"
|
||||||
"github.com/docker/go-connections/nat"
|
|
||||||
"github.com/docker/libnetwork"
|
"github.com/docker/libnetwork"
|
||||||
nwconfig "github.com/docker/libnetwork/config"
|
nwconfig "github.com/docker/libnetwork/config"
|
||||||
"github.com/docker/libtrust"
|
"github.com/docker/libtrust"
|
||||||
"golang.org/x/net/context"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -317,35 +310,6 @@ func (daemon *Daemon) waitForNetworks(c *container.Container) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (daemon *Daemon) generateHostname(id string, config *containertypes.Config) {
|
|
||||||
// Generate default hostname
|
|
||||||
if config.Hostname == "" {
|
|
||||||
config.Hostname = id[:12]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (daemon *Daemon) getEntrypointAndArgs(configEntrypoint strslice.StrSlice, configCmd strslice.StrSlice) (string, []string) {
|
|
||||||
if len(configEntrypoint) != 0 {
|
|
||||||
return configEntrypoint[0], append(configEntrypoint[1:], configCmd...)
|
|
||||||
}
|
|
||||||
return configCmd[0], configCmd[1:]
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetLabels for a container or image id
|
|
||||||
func (daemon *Daemon) GetLabels(id string) map[string]string {
|
|
||||||
// TODO: TestCase
|
|
||||||
container := daemon.containers.Get(id)
|
|
||||||
if container != nil {
|
|
||||||
return container.Config.Labels
|
|
||||||
}
|
|
||||||
|
|
||||||
img, err := daemon.GetImage(id)
|
|
||||||
if err == nil {
|
|
||||||
return img.ContainerConfig.Labels
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (daemon *Daemon) children(c *container.Container) map[string]*container.Container {
|
func (daemon *Daemon) children(c *container.Container) map[string]*container.Container {
|
||||||
return daemon.linkIndex.children(c)
|
return daemon.linkIndex.children(c)
|
||||||
}
|
}
|
||||||
|
@ -762,37 +726,6 @@ func tempDir(rootDir string, rootUID, rootGID int) (string, error) {
|
||||||
return tmpDir, idtools.MkdirAllAs(tmpDir, 0700, rootUID, rootGID)
|
return tmpDir, idtools.MkdirAllAs(tmpDir, 0700, rootUID, rootGID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (daemon *Daemon) setSecurityOptions(container *container.Container, hostConfig *containertypes.HostConfig) error {
|
|
||||||
container.Lock()
|
|
||||||
defer container.Unlock()
|
|
||||||
return parseSecurityOpt(container, hostConfig)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (daemon *Daemon) setHostConfig(container *container.Container, hostConfig *containertypes.HostConfig) error {
|
|
||||||
// Do not lock while creating volumes since this could be calling out to external plugins
|
|
||||||
// Don't want to block other actions, like `docker ps` because we're waiting on an external plugin
|
|
||||||
if err := daemon.registerMountPoints(container, hostConfig); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
container.Lock()
|
|
||||||
defer container.Unlock()
|
|
||||||
|
|
||||||
// Register any links from the host config before starting the container
|
|
||||||
if err := daemon.registerLinks(container, hostConfig); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// make sure links is not nil
|
|
||||||
// this ensures that on the next daemon restart we don't try to migrate from legacy sqlite links
|
|
||||||
if hostConfig.Links == nil {
|
|
||||||
hostConfig.Links = []string{}
|
|
||||||
}
|
|
||||||
|
|
||||||
container.HostConfig = hostConfig
|
|
||||||
return container.ToDisk()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (daemon *Daemon) setupInitLayer(initPath string) error {
|
func (daemon *Daemon) setupInitLayer(initPath string) error {
|
||||||
rootUID, rootGID := daemon.GetRemappedUIDGID()
|
rootUID, rootGID := daemon.GetRemappedUIDGID()
|
||||||
return setupInitLayer(initPath, rootUID, rootGID)
|
return setupInitLayer(initPath, rootUID, rootGID)
|
||||||
|
@ -806,73 +739,6 @@ func setDefaultMtu(config *Config) {
|
||||||
config.Mtu = defaultNetworkMtu
|
config.Mtu = defaultNetworkMtu
|
||||||
}
|
}
|
||||||
|
|
||||||
// verifyContainerSettings performs validation of the hostconfig and config
|
|
||||||
// structures.
|
|
||||||
func (daemon *Daemon) verifyContainerSettings(hostConfig *containertypes.HostConfig, config *containertypes.Config, update bool) ([]string, error) {
|
|
||||||
|
|
||||||
// First perform verification of settings common across all platforms.
|
|
||||||
if config != nil {
|
|
||||||
if config.WorkingDir != "" {
|
|
||||||
config.WorkingDir = filepath.FromSlash(config.WorkingDir) // Ensure in platform semantics
|
|
||||||
if !system.IsAbs(config.WorkingDir) {
|
|
||||||
return nil, fmt.Errorf("The working directory '%s' is invalid. It needs to be an absolute path", config.WorkingDir)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(config.StopSignal) > 0 {
|
|
||||||
_, err := signal.ParseSignal(config.StopSignal)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate if the given hostname is RFC 1123 (https://tools.ietf.org/html/rfc1123) compliant.
|
|
||||||
if len(config.Hostname) > 0 {
|
|
||||||
// RFC1123 specifies that 63 bytes is the maximium length
|
|
||||||
// Windows has the limitation of 63 bytes in length
|
|
||||||
// Linux hostname is limited to HOST_NAME_MAX=64, not not including the terminating null byte.
|
|
||||||
// We limit the length to 63 bytes here to match RFC1035 and RFC1123.
|
|
||||||
matched, _ := regexp.MatchString("^(([[:alnum:]]|[[:alnum:]][[:alnum:]\\-]*[[:alnum:]])\\.)*([[:alnum:]]|[[:alnum:]][[:alnum:]\\-]*[[:alnum:]])$", config.Hostname)
|
|
||||||
if len(config.Hostname) > 63 || !matched {
|
|
||||||
return nil, fmt.Errorf("invalid hostname format: %s", config.Hostname)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if hostConfig == nil {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
for port := range hostConfig.PortBindings {
|
|
||||||
_, portStr := nat.SplitProtoPort(string(port))
|
|
||||||
if _, err := nat.ParsePort(portStr); err != nil {
|
|
||||||
return nil, fmt.Errorf("Invalid port specification: %q", portStr)
|
|
||||||
}
|
|
||||||
for _, pb := range hostConfig.PortBindings[port] {
|
|
||||||
_, err := nat.NewPort(nat.SplitProtoPort(pb.HostPort))
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("Invalid port specification: %q", pb.HostPort)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now do platform-specific verification
|
|
||||||
return verifyPlatformContainerSettings(daemon, hostConfig, config, update)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Checks if the client set configurations for more than one network while creating a container
|
|
||||||
func (daemon *Daemon) verifyNetworkingConfig(nwConfig *networktypes.NetworkingConfig) error {
|
|
||||||
if nwConfig == nil || len(nwConfig.EndpointsConfig) <= 1 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
l := make([]string, 0, len(nwConfig.EndpointsConfig))
|
|
||||||
for k := range nwConfig.EndpointsConfig {
|
|
||||||
l = append(l, k)
|
|
||||||
}
|
|
||||||
err := fmt.Errorf("Container cannot be connected to network endpoints: %s", strings.Join(l, ", "))
|
|
||||||
return errors.NewBadRequestError(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func configureVolumes(config *Config, rootUID, rootGID int) (*store.VolumeStore, error) {
|
func configureVolumes(config *Config, rootUID, rootGID int) (*store.VolumeStore, error) {
|
||||||
volumesDriver, err := local.New(config.Root, rootUID, rootGID)
|
volumesDriver, err := local.New(config.Root, rootUID, rootGID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -883,84 +749,11 @@ func configureVolumes(config *Config, rootUID, rootGID int) (*store.VolumeStore,
|
||||||
return store.New(config.Root)
|
return store.New(config.Root)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AuthenticateToRegistry checks the validity of credentials in authConfig
|
|
||||||
func (daemon *Daemon) AuthenticateToRegistry(ctx context.Context, authConfig *types.AuthConfig) (string, string, error) {
|
|
||||||
return daemon.RegistryService.Auth(ctx, authConfig, dockerversion.DockerUserAgent(ctx))
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsShuttingDown tells whether the daemon is shutting down or not
|
// IsShuttingDown tells whether the daemon is shutting down or not
|
||||||
func (daemon *Daemon) IsShuttingDown() bool {
|
func (daemon *Daemon) IsShuttingDown() bool {
|
||||||
return daemon.shutdown
|
return daemon.shutdown
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetContainerStats collects all the stats published by a container
|
|
||||||
func (daemon *Daemon) GetContainerStats(container *container.Container) (*types.StatsJSON, error) {
|
|
||||||
stats, err := daemon.stats(container)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if stats.Networks, err = daemon.getNetworkStats(container); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return stats, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resolve Network SandboxID in case the container reuse another container's network stack
|
|
||||||
func (daemon *Daemon) getNetworkSandboxID(c *container.Container) (string, error) {
|
|
||||||
curr := c
|
|
||||||
for curr.HostConfig.NetworkMode.IsContainer() {
|
|
||||||
containerID := curr.HostConfig.NetworkMode.ConnectedContainer()
|
|
||||||
connected, err := daemon.GetContainer(containerID)
|
|
||||||
if err != nil {
|
|
||||||
return "", fmt.Errorf("Could not get container for %s", containerID)
|
|
||||||
}
|
|
||||||
curr = connected
|
|
||||||
}
|
|
||||||
return curr.NetworkSettings.SandboxID, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (daemon *Daemon) getNetworkStats(c *container.Container) (map[string]types.NetworkStats, error) {
|
|
||||||
sandboxID, err := daemon.getNetworkSandboxID(c)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
sb, err := daemon.netController.SandboxByID(sandboxID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
lnstats, err := sb.Statistics()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
stats := make(map[string]types.NetworkStats)
|
|
||||||
// Convert libnetwork nw stats into engine-api stats
|
|
||||||
for ifName, ifStats := range lnstats {
|
|
||||||
stats[ifName] = types.NetworkStats{
|
|
||||||
RxBytes: ifStats.RxBytes,
|
|
||||||
RxPackets: ifStats.RxPackets,
|
|
||||||
RxErrors: ifStats.RxErrors,
|
|
||||||
RxDropped: ifStats.RxDropped,
|
|
||||||
TxBytes: ifStats.TxBytes,
|
|
||||||
TxPackets: ifStats.TxPackets,
|
|
||||||
TxErrors: ifStats.TxErrors,
|
|
||||||
TxDropped: ifStats.TxDropped,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return stats, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// newBaseContainer creates a new container with its initial
|
|
||||||
// configuration based on the root storage from the daemon.
|
|
||||||
func (daemon *Daemon) newBaseContainer(id string) *container.Container {
|
|
||||||
return container.NewBaseContainer(id, daemon.containerRoot(id))
|
|
||||||
}
|
|
||||||
|
|
||||||
// initDiscovery initializes the discovery watcher for this daemon.
|
// initDiscovery initializes the discovery watcher for this daemon.
|
||||||
func (daemon *Daemon) initDiscovery(config *Config) error {
|
func (daemon *Daemon) initDiscovery(config *Config) error {
|
||||||
advertise, err := parseClusterAdvertiseSettings(config.ClusterStore, config.ClusterAdvertise)
|
advertise, err := parseClusterAdvertiseSettings(config.ClusterStore, config.ClusterAdvertise)
|
||||||
|
@ -1112,13 +905,6 @@ func (daemon *Daemon) reloadClusterDiscovery(config *Config) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateID(id string) error {
|
|
||||||
if id == "" {
|
|
||||||
return fmt.Errorf("Invalid empty id")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func isBridgeNetworkDisabled(config *Config) bool {
|
func isBridgeNetworkDisabled(config *Config) bool {
|
||||||
return config.bridgeConfig.Iface == disableNetworkBridge
|
return config.bridgeConfig.Iface == disableNetworkBridge
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,3 +106,10 @@ func (daemon *Daemon) generateNewName(id string) (string, error) {
|
||||||
}
|
}
|
||||||
return name, nil
|
return name, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func validateID(id string) error {
|
||||||
|
if id == "" {
|
||||||
|
return fmt.Errorf("Invalid empty id")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package daemon
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
|
@ -130,3 +131,65 @@ func (daemon *Daemon) subscribeToContainerStats(c *container.Container) chan int
|
||||||
func (daemon *Daemon) unsubscribeToContainerStats(c *container.Container, ch chan interface{}) {
|
func (daemon *Daemon) unsubscribeToContainerStats(c *container.Container, ch chan interface{}) {
|
||||||
daemon.statsCollector.unsubscribe(c, ch)
|
daemon.statsCollector.unsubscribe(c, ch)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetContainerStats collects all the stats published by a container
|
||||||
|
func (daemon *Daemon) GetContainerStats(container *container.Container) (*types.StatsJSON, error) {
|
||||||
|
stats, err := daemon.stats(container)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if stats.Networks, err = daemon.getNetworkStats(container); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return stats, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resolve Network SandboxID in case the container reuse another container's network stack
|
||||||
|
func (daemon *Daemon) getNetworkSandboxID(c *container.Container) (string, error) {
|
||||||
|
curr := c
|
||||||
|
for curr.HostConfig.NetworkMode.IsContainer() {
|
||||||
|
containerID := curr.HostConfig.NetworkMode.ConnectedContainer()
|
||||||
|
connected, err := daemon.GetContainer(containerID)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("Could not get container for %s", containerID)
|
||||||
|
}
|
||||||
|
curr = connected
|
||||||
|
}
|
||||||
|
return curr.NetworkSettings.SandboxID, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (daemon *Daemon) getNetworkStats(c *container.Container) (map[string]types.NetworkStats, error) {
|
||||||
|
sandboxID, err := daemon.getNetworkSandboxID(c)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
sb, err := daemon.netController.SandboxByID(sandboxID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
lnstats, err := sb.Statistics()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
stats := make(map[string]types.NetworkStats)
|
||||||
|
// Convert libnetwork nw stats into engine-api stats
|
||||||
|
for ifName, ifStats := range lnstats {
|
||||||
|
stats[ifName] = types.NetworkStats{
|
||||||
|
RxBytes: ifStats.RxBytes,
|
||||||
|
RxPackets: ifStats.RxPackets,
|
||||||
|
RxErrors: ifStats.RxErrors,
|
||||||
|
RxDropped: ifStats.RxDropped,
|
||||||
|
TxBytes: ifStats.TxBytes,
|
||||||
|
TxPackets: ifStats.TxPackets,
|
||||||
|
TxErrors: ifStats.TxErrors,
|
||||||
|
TxDropped: ifStats.TxDropped,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return stats, nil
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue