Signed-off-by: Vincent Demeester <vincent@sbr.pm>
| 1 | 1 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,13 @@ |
| 0 |
+package daemon |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "golang.org/x/net/context" |
|
| 4 |
+ |
|
| 5 |
+ "github.com/docker/docker/dockerversion" |
|
| 6 |
+ "github.com/docker/engine-api/types" |
|
| 7 |
+) |
|
| 8 |
+ |
|
| 9 |
+// AuthenticateToRegistry checks the validity of credentials in authConfig |
|
| 10 |
+func (daemon *Daemon) AuthenticateToRegistry(ctx context.Context, authConfig *types.AuthConfig) (string, string, error) {
|
|
| 11 |
+ return daemon.RegistryService.Auth(ctx, authConfig, dockerversion.DockerUserAgent(ctx)) |
|
| 12 |
+} |
| ... | ... |
@@ -3,14 +3,19 @@ package daemon |
| 3 | 3 |
import ( |
| 4 | 4 |
"fmt" |
| 5 | 5 |
"path/filepath" |
| 6 |
+ "regexp" |
|
| 6 | 7 |
"time" |
| 7 | 8 |
|
| 8 | 9 |
"github.com/docker/docker/container" |
| 9 | 10 |
"github.com/docker/docker/daemon/network" |
| 10 | 11 |
"github.com/docker/docker/errors" |
| 11 | 12 |
"github.com/docker/docker/image" |
| 13 |
+ "github.com/docker/docker/pkg/signal" |
|
| 14 |
+ "github.com/docker/docker/pkg/system" |
|
| 12 | 15 |
"github.com/docker/docker/pkg/truncindex" |
| 13 | 16 |
containertypes "github.com/docker/engine-api/types/container" |
| 17 |
+ "github.com/docker/engine-api/types/strslice" |
|
| 18 |
+ "github.com/docker/go-connections/nat" |
|
| 14 | 19 |
) |
| 15 | 20 |
|
| 16 | 21 |
// 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) {
|
| 143 | 143 |
} |
| 144 | 144 |
return e, nil |
| 145 | 145 |
} |
| 146 |
+ |
|
| 147 |
+// newBaseContainer creates a new container with its initial |
|
| 148 |
+// configuration based on the root storage from the daemon. |
|
| 149 |
+func (daemon *Daemon) newBaseContainer(id string) *container.Container {
|
|
| 150 |
+ return container.NewBaseContainer(id, daemon.containerRoot(id)) |
|
| 151 |
+} |
|
| 152 |
+ |
|
| 153 |
+func (daemon *Daemon) getEntrypointAndArgs(configEntrypoint strslice.StrSlice, configCmd strslice.StrSlice) (string, []string) {
|
|
| 154 |
+ if len(configEntrypoint) != 0 {
|
|
| 155 |
+ return configEntrypoint[0], append(configEntrypoint[1:], configCmd...) |
|
| 156 |
+ } |
|
| 157 |
+ return configCmd[0], configCmd[1:] |
|
| 158 |
+} |
|
| 159 |
+ |
|
| 160 |
+func (daemon *Daemon) generateHostname(id string, config *containertypes.Config) {
|
|
| 161 |
+ // Generate default hostname |
|
| 162 |
+ if config.Hostname == "" {
|
|
| 163 |
+ config.Hostname = id[:12] |
|
| 164 |
+ } |
|
| 165 |
+} |
|
| 166 |
+ |
|
| 167 |
+func (daemon *Daemon) setSecurityOptions(container *container.Container, hostConfig *containertypes.HostConfig) error {
|
|
| 168 |
+ container.Lock() |
|
| 169 |
+ defer container.Unlock() |
|
| 170 |
+ return parseSecurityOpt(container, hostConfig) |
|
| 171 |
+} |
|
| 172 |
+ |
|
| 173 |
+func (daemon *Daemon) setHostConfig(container *container.Container, hostConfig *containertypes.HostConfig) error {
|
|
| 174 |
+ // Do not lock while creating volumes since this could be calling out to external plugins |
|
| 175 |
+ // Don't want to block other actions, like `docker ps` because we're waiting on an external plugin |
|
| 176 |
+ if err := daemon.registerMountPoints(container, hostConfig); err != nil {
|
|
| 177 |
+ return err |
|
| 178 |
+ } |
|
| 179 |
+ |
|
| 180 |
+ container.Lock() |
|
| 181 |
+ defer container.Unlock() |
|
| 182 |
+ |
|
| 183 |
+ // Register any links from the host config before starting the container |
|
| 184 |
+ if err := daemon.registerLinks(container, hostConfig); err != nil {
|
|
| 185 |
+ return err |
|
| 186 |
+ } |
|
| 187 |
+ |
|
| 188 |
+ // make sure links is not nil |
|
| 189 |
+ // this ensures that on the next daemon restart we don't try to migrate from legacy sqlite links |
|
| 190 |
+ if hostConfig.Links == nil {
|
|
| 191 |
+ hostConfig.Links = []string{}
|
|
| 192 |
+ } |
|
| 193 |
+ |
|
| 194 |
+ container.HostConfig = hostConfig |
|
| 195 |
+ return container.ToDisk() |
|
| 196 |
+} |
|
| 197 |
+ |
|
| 198 |
+// verifyContainerSettings performs validation of the hostconfig and config |
|
| 199 |
+// structures. |
|
| 200 |
+func (daemon *Daemon) verifyContainerSettings(hostConfig *containertypes.HostConfig, config *containertypes.Config, update bool) ([]string, error) {
|
|
| 201 |
+ |
|
| 202 |
+ // First perform verification of settings common across all platforms. |
|
| 203 |
+ if config != nil {
|
|
| 204 |
+ if config.WorkingDir != "" {
|
|
| 205 |
+ config.WorkingDir = filepath.FromSlash(config.WorkingDir) // Ensure in platform semantics |
|
| 206 |
+ if !system.IsAbs(config.WorkingDir) {
|
|
| 207 |
+ return nil, fmt.Errorf("The working directory '%s' is invalid. It needs to be an absolute path", config.WorkingDir)
|
|
| 208 |
+ } |
|
| 209 |
+ } |
|
| 210 |
+ |
|
| 211 |
+ if len(config.StopSignal) > 0 {
|
|
| 212 |
+ _, err := signal.ParseSignal(config.StopSignal) |
|
| 213 |
+ if err != nil {
|
|
| 214 |
+ return nil, err |
|
| 215 |
+ } |
|
| 216 |
+ } |
|
| 217 |
+ |
|
| 218 |
+ // Validate if the given hostname is RFC 1123 (https://tools.ietf.org/html/rfc1123) compliant. |
|
| 219 |
+ if len(config.Hostname) > 0 {
|
|
| 220 |
+ // RFC1123 specifies that 63 bytes is the maximium length |
|
| 221 |
+ // Windows has the limitation of 63 bytes in length |
|
| 222 |
+ // Linux hostname is limited to HOST_NAME_MAX=64, not not including the terminating null byte. |
|
| 223 |
+ // We limit the length to 63 bytes here to match RFC1035 and RFC1123. |
|
| 224 |
+ matched, _ := regexp.MatchString("^(([[:alnum:]]|[[:alnum:]][[:alnum:]\\-]*[[:alnum:]])\\.)*([[:alnum:]]|[[:alnum:]][[:alnum:]\\-]*[[:alnum:]])$", config.Hostname)
|
|
| 225 |
+ if len(config.Hostname) > 63 || !matched {
|
|
| 226 |
+ return nil, fmt.Errorf("invalid hostname format: %s", config.Hostname)
|
|
| 227 |
+ } |
|
| 228 |
+ } |
|
| 229 |
+ } |
|
| 230 |
+ |
|
| 231 |
+ if hostConfig == nil {
|
|
| 232 |
+ return nil, nil |
|
| 233 |
+ } |
|
| 234 |
+ |
|
| 235 |
+ for port := range hostConfig.PortBindings {
|
|
| 236 |
+ _, portStr := nat.SplitProtoPort(string(port)) |
|
| 237 |
+ if _, err := nat.ParsePort(portStr); err != nil {
|
|
| 238 |
+ return nil, fmt.Errorf("Invalid port specification: %q", portStr)
|
|
| 239 |
+ } |
|
| 240 |
+ for _, pb := range hostConfig.PortBindings[port] {
|
|
| 241 |
+ _, err := nat.NewPort(nat.SplitProtoPort(pb.HostPort)) |
|
| 242 |
+ if err != nil {
|
|
| 243 |
+ return nil, fmt.Errorf("Invalid port specification: %q", pb.HostPort)
|
|
| 244 |
+ } |
|
| 245 |
+ } |
|
| 246 |
+ } |
|
| 247 |
+ |
|
| 248 |
+ // Now do platform-specific verification |
|
| 249 |
+ return verifyPlatformContainerSettings(daemon, hostConfig, config, update) |
|
| 250 |
+} |
| ... | ... |
@@ -2,9 +2,11 @@ package daemon |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 | 4 |
"fmt" |
| 5 |
+ "strings" |
|
| 5 | 6 |
|
| 6 | 7 |
"github.com/Sirupsen/logrus" |
| 7 | 8 |
"github.com/docker/docker/container" |
| 9 |
+ "github.com/docker/docker/errors" |
|
| 8 | 10 |
"github.com/docker/docker/image" |
| 9 | 11 |
"github.com/docker/docker/layer" |
| 10 | 12 |
"github.com/docker/docker/pkg/idtools" |
| ... | ... |
@@ -234,3 +236,16 @@ func (daemon *Daemon) mergeAndVerifyConfig(config *containertypes.Config, img *i |
| 234 | 234 |
} |
| 235 | 235 |
return nil |
| 236 | 236 |
} |
| 237 |
+ |
|
| 238 |
+// Checks if the client set configurations for more than one network while creating a container |
|
| 239 |
+func (daemon *Daemon) verifyNetworkingConfig(nwConfig *networktypes.NetworkingConfig) error {
|
|
| 240 |
+ if nwConfig == nil || len(nwConfig.EndpointsConfig) <= 1 {
|
|
| 241 |
+ return nil |
|
| 242 |
+ } |
|
| 243 |
+ l := make([]string, 0, len(nwConfig.EndpointsConfig)) |
|
| 244 |
+ for k := range nwConfig.EndpointsConfig {
|
|
| 245 |
+ l = append(l, k) |
|
| 246 |
+ } |
|
| 247 |
+ err := fmt.Errorf("Container cannot be connected to network endpoints: %s", strings.Join(l, ", "))
|
|
| 248 |
+ return errors.NewBadRequestError(err) |
|
| 249 |
+} |
| ... | ... |
@@ -14,7 +14,6 @@ import ( |
| 14 | 14 |
"os" |
| 15 | 15 |
"path" |
| 16 | 16 |
"path/filepath" |
| 17 |
- "regexp" |
|
| 18 | 17 |
"runtime" |
| 19 | 18 |
"strings" |
| 20 | 19 |
"sync" |
| ... | ... |
@@ -27,16 +26,12 @@ import ( |
| 27 | 27 |
"github.com/docker/docker/container" |
| 28 | 28 |
"github.com/docker/docker/daemon/events" |
| 29 | 29 |
"github.com/docker/docker/daemon/exec" |
| 30 |
- "github.com/docker/docker/errors" |
|
| 31 | 30 |
"github.com/docker/engine-api/types" |
| 32 | 31 |
containertypes "github.com/docker/engine-api/types/container" |
| 33 |
- networktypes "github.com/docker/engine-api/types/network" |
|
| 34 |
- "github.com/docker/engine-api/types/strslice" |
|
| 35 | 32 |
// register graph drivers |
| 36 | 33 |
_ "github.com/docker/docker/daemon/graphdriver/register" |
| 37 | 34 |
dmetadata "github.com/docker/docker/distribution/metadata" |
| 38 | 35 |
"github.com/docker/docker/distribution/xfer" |
| 39 |
- "github.com/docker/docker/dockerversion" |
|
| 40 | 36 |
"github.com/docker/docker/image" |
| 41 | 37 |
"github.com/docker/docker/layer" |
| 42 | 38 |
"github.com/docker/docker/libcontainerd" |
| ... | ... |
@@ -58,11 +53,9 @@ import ( |
| 58 | 58 |
volumedrivers "github.com/docker/docker/volume/drivers" |
| 59 | 59 |
"github.com/docker/docker/volume/local" |
| 60 | 60 |
"github.com/docker/docker/volume/store" |
| 61 |
- "github.com/docker/go-connections/nat" |
|
| 62 | 61 |
"github.com/docker/libnetwork" |
| 63 | 62 |
nwconfig "github.com/docker/libnetwork/config" |
| 64 | 63 |
"github.com/docker/libtrust" |
| 65 |
- "golang.org/x/net/context" |
|
| 66 | 64 |
) |
| 67 | 65 |
|
| 68 | 66 |
var ( |
| ... | ... |
@@ -317,35 +310,6 @@ func (daemon *Daemon) waitForNetworks(c *container.Container) {
|
| 317 | 317 |
} |
| 318 | 318 |
} |
| 319 | 319 |
|
| 320 |
-func (daemon *Daemon) generateHostname(id string, config *containertypes.Config) {
|
|
| 321 |
- // Generate default hostname |
|
| 322 |
- if config.Hostname == "" {
|
|
| 323 |
- config.Hostname = id[:12] |
|
| 324 |
- } |
|
| 325 |
-} |
|
| 326 |
- |
|
| 327 |
-func (daemon *Daemon) getEntrypointAndArgs(configEntrypoint strslice.StrSlice, configCmd strslice.StrSlice) (string, []string) {
|
|
| 328 |
- if len(configEntrypoint) != 0 {
|
|
| 329 |
- return configEntrypoint[0], append(configEntrypoint[1:], configCmd...) |
|
| 330 |
- } |
|
| 331 |
- return configCmd[0], configCmd[1:] |
|
| 332 |
-} |
|
| 333 |
- |
|
| 334 |
-// GetLabels for a container or image id |
|
| 335 |
-func (daemon *Daemon) GetLabels(id string) map[string]string {
|
|
| 336 |
- // TODO: TestCase |
|
| 337 |
- container := daemon.containers.Get(id) |
|
| 338 |
- if container != nil {
|
|
| 339 |
- return container.Config.Labels |
|
| 340 |
- } |
|
| 341 |
- |
|
| 342 |
- img, err := daemon.GetImage(id) |
|
| 343 |
- if err == nil {
|
|
| 344 |
- return img.ContainerConfig.Labels |
|
| 345 |
- } |
|
| 346 |
- return nil |
|
| 347 |
-} |
|
| 348 |
- |
|
| 349 | 320 |
func (daemon *Daemon) children(c *container.Container) map[string]*container.Container {
|
| 350 | 321 |
return daemon.linkIndex.children(c) |
| 351 | 322 |
} |
| ... | ... |
@@ -762,37 +726,6 @@ func tempDir(rootDir string, rootUID, rootGID int) (string, error) {
|
| 762 | 762 |
return tmpDir, idtools.MkdirAllAs(tmpDir, 0700, rootUID, rootGID) |
| 763 | 763 |
} |
| 764 | 764 |
|
| 765 |
-func (daemon *Daemon) setSecurityOptions(container *container.Container, hostConfig *containertypes.HostConfig) error {
|
|
| 766 |
- container.Lock() |
|
| 767 |
- defer container.Unlock() |
|
| 768 |
- return parseSecurityOpt(container, hostConfig) |
|
| 769 |
-} |
|
| 770 |
- |
|
| 771 |
-func (daemon *Daemon) setHostConfig(container *container.Container, hostConfig *containertypes.HostConfig) error {
|
|
| 772 |
- // Do not lock while creating volumes since this could be calling out to external plugins |
|
| 773 |
- // Don't want to block other actions, like `docker ps` because we're waiting on an external plugin |
|
| 774 |
- if err := daemon.registerMountPoints(container, hostConfig); err != nil {
|
|
| 775 |
- return err |
|
| 776 |
- } |
|
| 777 |
- |
|
| 778 |
- container.Lock() |
|
| 779 |
- defer container.Unlock() |
|
| 780 |
- |
|
| 781 |
- // Register any links from the host config before starting the container |
|
| 782 |
- if err := daemon.registerLinks(container, hostConfig); err != nil {
|
|
| 783 |
- return err |
|
| 784 |
- } |
|
| 785 |
- |
|
| 786 |
- // make sure links is not nil |
|
| 787 |
- // this ensures that on the next daemon restart we don't try to migrate from legacy sqlite links |
|
| 788 |
- if hostConfig.Links == nil {
|
|
| 789 |
- hostConfig.Links = []string{}
|
|
| 790 |
- } |
|
| 791 |
- |
|
| 792 |
- container.HostConfig = hostConfig |
|
| 793 |
- return container.ToDisk() |
|
| 794 |
-} |
|
| 795 |
- |
|
| 796 | 765 |
func (daemon *Daemon) setupInitLayer(initPath string) error {
|
| 797 | 766 |
rootUID, rootGID := daemon.GetRemappedUIDGID() |
| 798 | 767 |
return setupInitLayer(initPath, rootUID, rootGID) |
| ... | ... |
@@ -806,73 +739,6 @@ func setDefaultMtu(config *Config) {
|
| 806 | 806 |
config.Mtu = defaultNetworkMtu |
| 807 | 807 |
} |
| 808 | 808 |
|
| 809 |
-// verifyContainerSettings performs validation of the hostconfig and config |
|
| 810 |
-// structures. |
|
| 811 |
-func (daemon *Daemon) verifyContainerSettings(hostConfig *containertypes.HostConfig, config *containertypes.Config, update bool) ([]string, error) {
|
|
| 812 |
- |
|
| 813 |
- // First perform verification of settings common across all platforms. |
|
| 814 |
- if config != nil {
|
|
| 815 |
- if config.WorkingDir != "" {
|
|
| 816 |
- config.WorkingDir = filepath.FromSlash(config.WorkingDir) // Ensure in platform semantics |
|
| 817 |
- if !system.IsAbs(config.WorkingDir) {
|
|
| 818 |
- return nil, fmt.Errorf("The working directory '%s' is invalid. It needs to be an absolute path", config.WorkingDir)
|
|
| 819 |
- } |
|
| 820 |
- } |
|
| 821 |
- |
|
| 822 |
- if len(config.StopSignal) > 0 {
|
|
| 823 |
- _, err := signal.ParseSignal(config.StopSignal) |
|
| 824 |
- if err != nil {
|
|
| 825 |
- return nil, err |
|
| 826 |
- } |
|
| 827 |
- } |
|
| 828 |
- |
|
| 829 |
- // Validate if the given hostname is RFC 1123 (https://tools.ietf.org/html/rfc1123) compliant. |
|
| 830 |
- if len(config.Hostname) > 0 {
|
|
| 831 |
- // RFC1123 specifies that 63 bytes is the maximium length |
|
| 832 |
- // Windows has the limitation of 63 bytes in length |
|
| 833 |
- // Linux hostname is limited to HOST_NAME_MAX=64, not not including the terminating null byte. |
|
| 834 |
- // We limit the length to 63 bytes here to match RFC1035 and RFC1123. |
|
| 835 |
- matched, _ := regexp.MatchString("^(([[:alnum:]]|[[:alnum:]][[:alnum:]\\-]*[[:alnum:]])\\.)*([[:alnum:]]|[[:alnum:]][[:alnum:]\\-]*[[:alnum:]])$", config.Hostname)
|
|
| 836 |
- if len(config.Hostname) > 63 || !matched {
|
|
| 837 |
- return nil, fmt.Errorf("invalid hostname format: %s", config.Hostname)
|
|
| 838 |
- } |
|
| 839 |
- } |
|
| 840 |
- } |
|
| 841 |
- |
|
| 842 |
- if hostConfig == nil {
|
|
| 843 |
- return nil, nil |
|
| 844 |
- } |
|
| 845 |
- |
|
| 846 |
- for port := range hostConfig.PortBindings {
|
|
| 847 |
- _, portStr := nat.SplitProtoPort(string(port)) |
|
| 848 |
- if _, err := nat.ParsePort(portStr); err != nil {
|
|
| 849 |
- return nil, fmt.Errorf("Invalid port specification: %q", portStr)
|
|
| 850 |
- } |
|
| 851 |
- for _, pb := range hostConfig.PortBindings[port] {
|
|
| 852 |
- _, err := nat.NewPort(nat.SplitProtoPort(pb.HostPort)) |
|
| 853 |
- if err != nil {
|
|
| 854 |
- return nil, fmt.Errorf("Invalid port specification: %q", pb.HostPort)
|
|
| 855 |
- } |
|
| 856 |
- } |
|
| 857 |
- } |
|
| 858 |
- |
|
| 859 |
- // Now do platform-specific verification |
|
| 860 |
- return verifyPlatformContainerSettings(daemon, hostConfig, config, update) |
|
| 861 |
-} |
|
| 862 |
- |
|
| 863 |
-// Checks if the client set configurations for more than one network while creating a container |
|
| 864 |
-func (daemon *Daemon) verifyNetworkingConfig(nwConfig *networktypes.NetworkingConfig) error {
|
|
| 865 |
- if nwConfig == nil || len(nwConfig.EndpointsConfig) <= 1 {
|
|
| 866 |
- return nil |
|
| 867 |
- } |
|
| 868 |
- l := make([]string, 0, len(nwConfig.EndpointsConfig)) |
|
| 869 |
- for k := range nwConfig.EndpointsConfig {
|
|
| 870 |
- l = append(l, k) |
|
| 871 |
- } |
|
| 872 |
- err := fmt.Errorf("Container cannot be connected to network endpoints: %s", strings.Join(l, ", "))
|
|
| 873 |
- return errors.NewBadRequestError(err) |
|
| 874 |
-} |
|
| 875 |
- |
|
| 876 | 809 |
func configureVolumes(config *Config, rootUID, rootGID int) (*store.VolumeStore, error) {
|
| 877 | 810 |
volumesDriver, err := local.New(config.Root, rootUID, rootGID) |
| 878 | 811 |
if err != nil {
|
| ... | ... |
@@ -883,84 +749,11 @@ func configureVolumes(config *Config, rootUID, rootGID int) (*store.VolumeStore, |
| 883 | 883 |
return store.New(config.Root) |
| 884 | 884 |
} |
| 885 | 885 |
|
| 886 |
-// AuthenticateToRegistry checks the validity of credentials in authConfig |
|
| 887 |
-func (daemon *Daemon) AuthenticateToRegistry(ctx context.Context, authConfig *types.AuthConfig) (string, string, error) {
|
|
| 888 |
- return daemon.RegistryService.Auth(ctx, authConfig, dockerversion.DockerUserAgent(ctx)) |
|
| 889 |
-} |
|
| 890 |
- |
|
| 891 | 886 |
// IsShuttingDown tells whether the daemon is shutting down or not |
| 892 | 887 |
func (daemon *Daemon) IsShuttingDown() bool {
|
| 893 | 888 |
return daemon.shutdown |
| 894 | 889 |
} |
| 895 | 890 |
|
| 896 |
-// GetContainerStats collects all the stats published by a container |
|
| 897 |
-func (daemon *Daemon) GetContainerStats(container *container.Container) (*types.StatsJSON, error) {
|
|
| 898 |
- stats, err := daemon.stats(container) |
|
| 899 |
- if err != nil {
|
|
| 900 |
- return nil, err |
|
| 901 |
- } |
|
| 902 |
- |
|
| 903 |
- if stats.Networks, err = daemon.getNetworkStats(container); err != nil {
|
|
| 904 |
- return nil, err |
|
| 905 |
- } |
|
| 906 |
- |
|
| 907 |
- return stats, nil |
|
| 908 |
-} |
|
| 909 |
- |
|
| 910 |
-// Resolve Network SandboxID in case the container reuse another container's network stack |
|
| 911 |
-func (daemon *Daemon) getNetworkSandboxID(c *container.Container) (string, error) {
|
|
| 912 |
- curr := c |
|
| 913 |
- for curr.HostConfig.NetworkMode.IsContainer() {
|
|
| 914 |
- containerID := curr.HostConfig.NetworkMode.ConnectedContainer() |
|
| 915 |
- connected, err := daemon.GetContainer(containerID) |
|
| 916 |
- if err != nil {
|
|
| 917 |
- return "", fmt.Errorf("Could not get container for %s", containerID)
|
|
| 918 |
- } |
|
| 919 |
- curr = connected |
|
| 920 |
- } |
|
| 921 |
- return curr.NetworkSettings.SandboxID, nil |
|
| 922 |
-} |
|
| 923 |
- |
|
| 924 |
-func (daemon *Daemon) getNetworkStats(c *container.Container) (map[string]types.NetworkStats, error) {
|
|
| 925 |
- sandboxID, err := daemon.getNetworkSandboxID(c) |
|
| 926 |
- if err != nil {
|
|
| 927 |
- return nil, err |
|
| 928 |
- } |
|
| 929 |
- |
|
| 930 |
- sb, err := daemon.netController.SandboxByID(sandboxID) |
|
| 931 |
- if err != nil {
|
|
| 932 |
- return nil, err |
|
| 933 |
- } |
|
| 934 |
- |
|
| 935 |
- lnstats, err := sb.Statistics() |
|
| 936 |
- if err != nil {
|
|
| 937 |
- return nil, err |
|
| 938 |
- } |
|
| 939 |
- |
|
| 940 |
- stats := make(map[string]types.NetworkStats) |
|
| 941 |
- // Convert libnetwork nw stats into engine-api stats |
|
| 942 |
- for ifName, ifStats := range lnstats {
|
|
| 943 |
- stats[ifName] = types.NetworkStats{
|
|
| 944 |
- RxBytes: ifStats.RxBytes, |
|
| 945 |
- RxPackets: ifStats.RxPackets, |
|
| 946 |
- RxErrors: ifStats.RxErrors, |
|
| 947 |
- RxDropped: ifStats.RxDropped, |
|
| 948 |
- TxBytes: ifStats.TxBytes, |
|
| 949 |
- TxPackets: ifStats.TxPackets, |
|
| 950 |
- TxErrors: ifStats.TxErrors, |
|
| 951 |
- TxDropped: ifStats.TxDropped, |
|
| 952 |
- } |
|
| 953 |
- } |
|
| 954 |
- |
|
| 955 |
- return stats, nil |
|
| 956 |
-} |
|
| 957 |
- |
|
| 958 |
-// newBaseContainer creates a new container with its initial |
|
| 959 |
-// configuration based on the root storage from the daemon. |
|
| 960 |
-func (daemon *Daemon) newBaseContainer(id string) *container.Container {
|
|
| 961 |
- return container.NewBaseContainer(id, daemon.containerRoot(id)) |
|
| 962 |
-} |
|
| 963 |
- |
|
| 964 | 891 |
// initDiscovery initializes the discovery watcher for this daemon. |
| 965 | 892 |
func (daemon *Daemon) initDiscovery(config *Config) error {
|
| 966 | 893 |
advertise, err := parseClusterAdvertiseSettings(config.ClusterStore, config.ClusterAdvertise) |
| ... | ... |
@@ -1112,13 +905,6 @@ func (daemon *Daemon) reloadClusterDiscovery(config *Config) error {
|
| 1112 | 1112 |
return nil |
| 1113 | 1113 |
} |
| 1114 | 1114 |
|
| 1115 |
-func validateID(id string) error {
|
|
| 1116 |
- if id == "" {
|
|
| 1117 |
- return fmt.Errorf("Invalid empty id")
|
|
| 1118 |
- } |
|
| 1119 |
- return nil |
|
| 1120 |
-} |
|
| 1121 |
- |
|
| 1122 | 1115 |
func isBridgeNetworkDisabled(config *Config) bool {
|
| 1123 | 1116 |
return config.bridgeConfig.Iface == disableNetworkBridge |
| 1124 | 1117 |
} |
| ... | ... |
@@ -3,6 +3,7 @@ package daemon |
| 3 | 3 |
import ( |
| 4 | 4 |
"encoding/json" |
| 5 | 5 |
"errors" |
| 6 |
+ "fmt" |
|
| 6 | 7 |
"runtime" |
| 7 | 8 |
|
| 8 | 9 |
"golang.org/x/net/context" |
| ... | ... |
@@ -130,3 +131,65 @@ func (daemon *Daemon) subscribeToContainerStats(c *container.Container) chan int |
| 130 | 130 |
func (daemon *Daemon) unsubscribeToContainerStats(c *container.Container, ch chan interface{}) {
|
| 131 | 131 |
daemon.statsCollector.unsubscribe(c, ch) |
| 132 | 132 |
} |
| 133 |
+ |
|
| 134 |
+// GetContainerStats collects all the stats published by a container |
|
| 135 |
+func (daemon *Daemon) GetContainerStats(container *container.Container) (*types.StatsJSON, error) {
|
|
| 136 |
+ stats, err := daemon.stats(container) |
|
| 137 |
+ if err != nil {
|
|
| 138 |
+ return nil, err |
|
| 139 |
+ } |
|
| 140 |
+ |
|
| 141 |
+ if stats.Networks, err = daemon.getNetworkStats(container); err != nil {
|
|
| 142 |
+ return nil, err |
|
| 143 |
+ } |
|
| 144 |
+ |
|
| 145 |
+ return stats, nil |
|
| 146 |
+} |
|
| 147 |
+ |
|
| 148 |
+// Resolve Network SandboxID in case the container reuse another container's network stack |
|
| 149 |
+func (daemon *Daemon) getNetworkSandboxID(c *container.Container) (string, error) {
|
|
| 150 |
+ curr := c |
|
| 151 |
+ for curr.HostConfig.NetworkMode.IsContainer() {
|
|
| 152 |
+ containerID := curr.HostConfig.NetworkMode.ConnectedContainer() |
|
| 153 |
+ connected, err := daemon.GetContainer(containerID) |
|
| 154 |
+ if err != nil {
|
|
| 155 |
+ return "", fmt.Errorf("Could not get container for %s", containerID)
|
|
| 156 |
+ } |
|
| 157 |
+ curr = connected |
|
| 158 |
+ } |
|
| 159 |
+ return curr.NetworkSettings.SandboxID, nil |
|
| 160 |
+} |
|
| 161 |
+ |
|
| 162 |
+func (daemon *Daemon) getNetworkStats(c *container.Container) (map[string]types.NetworkStats, error) {
|
|
| 163 |
+ sandboxID, err := daemon.getNetworkSandboxID(c) |
|
| 164 |
+ if err != nil {
|
|
| 165 |
+ return nil, err |
|
| 166 |
+ } |
|
| 167 |
+ |
|
| 168 |
+ sb, err := daemon.netController.SandboxByID(sandboxID) |
|
| 169 |
+ if err != nil {
|
|
| 170 |
+ return nil, err |
|
| 171 |
+ } |
|
| 172 |
+ |
|
| 173 |
+ lnstats, err := sb.Statistics() |
|
| 174 |
+ if err != nil {
|
|
| 175 |
+ return nil, err |
|
| 176 |
+ } |
|
| 177 |
+ |
|
| 178 |
+ stats := make(map[string]types.NetworkStats) |
|
| 179 |
+ // Convert libnetwork nw stats into engine-api stats |
|
| 180 |
+ for ifName, ifStats := range lnstats {
|
|
| 181 |
+ stats[ifName] = types.NetworkStats{
|
|
| 182 |
+ RxBytes: ifStats.RxBytes, |
|
| 183 |
+ RxPackets: ifStats.RxPackets, |
|
| 184 |
+ RxErrors: ifStats.RxErrors, |
|
| 185 |
+ RxDropped: ifStats.RxDropped, |
|
| 186 |
+ TxBytes: ifStats.TxBytes, |
|
| 187 |
+ TxPackets: ifStats.TxPackets, |
|
| 188 |
+ TxErrors: ifStats.TxErrors, |
|
| 189 |
+ TxDropped: ifStats.TxDropped, |
|
| 190 |
+ } |
|
| 191 |
+ } |
|
| 192 |
+ |
|
| 193 |
+ return stats, nil |
|
| 194 |
+} |