1package daemon // import "github.com/docker/docker/daemon"
2
3import (
4	"fmt"
5	"os"
6	"runtime"
7	"strings"
8	"time"
9
10	"github.com/docker/docker/api"
11	"github.com/docker/docker/api/types"
12	"github.com/docker/docker/cli/debug"
13	"github.com/docker/docker/daemon/logger"
14	"github.com/docker/docker/dockerversion"
15	"github.com/docker/docker/pkg/fileutils"
16	"github.com/docker/docker/pkg/parsers/kernel"
17	"github.com/docker/docker/pkg/parsers/operatingsystem"
18	"github.com/docker/docker/pkg/platform"
19	"github.com/docker/docker/pkg/sysinfo"
20	"github.com/docker/docker/pkg/system"
21	"github.com/docker/docker/registry"
22	"github.com/docker/go-connections/sockets"
23	"github.com/sirupsen/logrus"
24)
25
26// SystemInfo returns information about the host server the daemon is running on.
27func (daemon *Daemon) SystemInfo() (*types.Info, error) {
28	kernelVersion := "<unknown>"
29	if kv, err := kernel.GetKernelVersion(); err != nil {
30		logrus.Warnf("Could not get kernel version: %v", err)
31	} else {
32		kernelVersion = kv.String()
33	}
34
35	operatingSystem := "<unknown>"
36	if s, err := operatingsystem.GetOperatingSystem(); err != nil {
37		logrus.Warnf("Could not get operating system name: %v", err)
38	} else {
39		operatingSystem = s
40	}
41
42	// Don't do containerized check on Windows
43	if runtime.GOOS != "windows" {
44		if inContainer, err := operatingsystem.IsContainerized(); err != nil {
45			logrus.Errorf("Could not determine if daemon is containerized: %v", err)
46			operatingSystem += " (error determining if containerized)"
47		} else if inContainer {
48			operatingSystem += " (containerized)"
49		}
50	}
51
52	meminfo, err := system.ReadMemInfo()
53	if err != nil {
54		logrus.Errorf("Could not read system memory info: %v", err)
55		meminfo = &system.MemInfo{}
56	}
57
58	sysInfo := sysinfo.New(true)
59	cRunning, cPaused, cStopped := stateCtr.get()
60
61	securityOptions := []string{}
62	if sysInfo.AppArmor {
63		securityOptions = append(securityOptions, "name=apparmor")
64	}
65	if sysInfo.Seccomp && supportsSeccomp {
66		profile := daemon.seccompProfilePath
67		if profile == "" {
68			profile = "default"
69		}
70		securityOptions = append(securityOptions, fmt.Sprintf("name=seccomp,profile=%s", profile))
71	}
72	if selinuxEnabled() {
73		securityOptions = append(securityOptions, "name=selinux")
74	}
75	rootIDs := daemon.idMappings.RootPair()
76	if rootIDs.UID != 0 || rootIDs.GID != 0 {
77		securityOptions = append(securityOptions, "name=userns")
78	}
79
80	var ds [][2]string
81	drivers := ""
82	statuses := daemon.imageService.LayerStoreStatus()
83	for os, gd := range daemon.graphDrivers {
84		ds = append(ds, statuses[os]...)
85		drivers += gd
86		if len(daemon.graphDrivers) > 1 {
87			drivers += fmt.Sprintf(" (%s) ", os)
88		}
89	}
90	drivers = strings.TrimSpace(drivers)
91
92	v := &types.Info{
93		ID:                 daemon.ID,
94		Containers:         cRunning + cPaused + cStopped,
95		ContainersRunning:  cRunning,
96		ContainersPaused:   cPaused,
97		ContainersStopped:  cStopped,
98		Images:             daemon.imageService.CountImages(),
99		Driver:             drivers,
100		DriverStatus:       ds,
101		Plugins:            daemon.showPluginsInfo(),
102		IPv4Forwarding:     !sysInfo.IPv4ForwardingDisabled,
103		BridgeNfIptables:   !sysInfo.BridgeNFCallIPTablesDisabled,
104		BridgeNfIP6tables:  !sysInfo.BridgeNFCallIP6TablesDisabled,
105		Debug:              debug.IsEnabled(),
106		NFd:                fileutils.GetTotalUsedFds(),
107		NGoroutines:        runtime.NumGoroutine(),
108		SystemTime:         time.Now().Format(time.RFC3339Nano),
109		LoggingDriver:      daemon.defaultLogConfig.Type,
110		CgroupDriver:       daemon.getCgroupDriver(),
111		NEventsListener:    daemon.EventsService.SubscribersCount(),
112		KernelVersion:      kernelVersion,
113		OperatingSystem:    operatingSystem,
114		IndexServerAddress: registry.IndexServer,
115		OSType:             platform.OSType,
116		Architecture:       platform.Architecture,
117		RegistryConfig:     daemon.RegistryService.ServiceConfig(),
118		NCPU:               sysinfo.NumCPU(),
119		MemTotal:           meminfo.MemTotal,
120		GenericResources:   daemon.genericResources,
121		DockerRootDir:      daemon.configStore.Root,
122		Labels:             daemon.configStore.Labels,
123		ExperimentalBuild:  daemon.configStore.Experimental,
124		ServerVersion:      dockerversion.Version,
125		ClusterStore:       daemon.configStore.ClusterStore,
126		ClusterAdvertise:   daemon.configStore.ClusterAdvertise,
127		HTTPProxy:          sockets.GetProxyEnv("http_proxy"),
128		HTTPSProxy:         sockets.GetProxyEnv("https_proxy"),
129		NoProxy:            sockets.GetProxyEnv("no_proxy"),
130		LiveRestoreEnabled: daemon.configStore.LiveRestoreEnabled,
131		SecurityOptions:    securityOptions,
132		Isolation:          daemon.defaultIsolation,
133	}
134
135	// Retrieve platform specific info
136	daemon.FillPlatformInfo(v, sysInfo)
137
138	hostname := ""
139	if hn, err := os.Hostname(); err != nil {
140		logrus.Warnf("Could not get hostname: %v", err)
141	} else {
142		hostname = hn
143	}
144	v.Name = hostname
145
146	return v, nil
147}
148
149// SystemVersion returns version information about the daemon.
150func (daemon *Daemon) SystemVersion() types.Version {
151	kernelVersion := "<unknown>"
152	if kv, err := kernel.GetKernelVersion(); err != nil {
153		logrus.Warnf("Could not get kernel version: %v", err)
154	} else {
155		kernelVersion = kv.String()
156	}
157
158	v := types.Version{
159		Components: []types.ComponentVersion{
160			{
161				Name:    "Engine",
162				Version: dockerversion.Version,
163				Details: map[string]string{
164					"GitCommit":     dockerversion.GitCommit,
165					"ApiVersion":    api.DefaultVersion,
166					"MinAPIVersion": api.MinVersion,
167					"GoVersion":     runtime.Version(),
168					"Os":            runtime.GOOS,
169					"Arch":          runtime.GOARCH,
170					"BuildTime":     dockerversion.BuildTime,
171					"KernelVersion": kernelVersion,
172					"Experimental":  fmt.Sprintf("%t", daemon.configStore.Experimental),
173				},
174			},
175		},
176
177		// Populate deprecated fields for older clients
178		Version:       dockerversion.Version,
179		GitCommit:     dockerversion.GitCommit,
180		APIVersion:    api.DefaultVersion,
181		MinAPIVersion: api.MinVersion,
182		GoVersion:     runtime.Version(),
183		Os:            runtime.GOOS,
184		Arch:          runtime.GOARCH,
185		BuildTime:     dockerversion.BuildTime,
186		KernelVersion: kernelVersion,
187		Experimental:  daemon.configStore.Experimental,
188	}
189
190	v.Platform.Name = dockerversion.PlatformName
191
192	return v
193}
194
195func (daemon *Daemon) showPluginsInfo() types.PluginsInfo {
196	var pluginsInfo types.PluginsInfo
197
198	pluginsInfo.Volume = daemon.volumes.GetDriverList()
199	pluginsInfo.Network = daemon.GetNetworkDriverList()
200	// The authorization plugins are returned in the order they are
201	// used as they constitute a request/response modification chain.
202	pluginsInfo.Authorization = daemon.configStore.AuthorizationPlugins
203	pluginsInfo.Log = logger.ListDrivers()
204
205	return pluginsInfo
206}
207