diff --git a/cmd/dockerd/daemon_solaris.go b/cmd/dockerd/daemon_solaris.go new file mode 100644 index 0000000000..a0f4908601 --- /dev/null +++ b/cmd/dockerd/daemon_solaris.go @@ -0,0 +1,74 @@ +// +build solaris + +package main + +import ( + "fmt" + "net" + "os" + "path/filepath" + "syscall" + + "github.com/docker/docker/libcontainerd" + "github.com/docker/docker/pkg/system" +) + +const defaultDaemonConfigFile = "" + +// currentUserIsOwner checks whether the current user is the owner of the given +// file. +func currentUserIsOwner(f string) bool { + if fileInfo, err := system.Stat(f); err == nil && fileInfo != nil { + if int(fileInfo.UID()) == os.Getuid() { + return true + } + } + return false +} + +// setDefaultUmask sets the umask to 0022 to avoid problems +// caused by custom umask +func setDefaultUmask() error { + desiredUmask := 0022 + syscall.Umask(desiredUmask) + if umask := syscall.Umask(desiredUmask); umask != desiredUmask { + return fmt.Errorf("failed to set umask: expected %#o, got %#o", desiredUmask, umask) + } + + return nil +} + +func getDaemonConfDir() string { + return "/etc/docker" +} + +// setupConfigReloadTrap configures the USR2 signal to reload the configuration. +func (cli *DaemonCli) setupConfigReloadTrap() { +} + +// notifySystem sends a message to the host when the server is ready to be used +func notifySystem() { +} + +func (cli *DaemonCli) getPlatformRemoteOptions() []libcontainerd.RemoteOption { + opts := []libcontainerd.RemoteOption{} + return opts +} + +// getLibcontainerdRoot gets the root directory for libcontainerd/containerd to +// store their state. +func (cli *DaemonCli) getLibcontainerdRoot() string { + return filepath.Join(cli.Config.ExecRoot, "libcontainerd") +} + +func allocateDaemonPort(addr string) error { + return nil +} + +// notifyShutdown is called after the daemon shuts down but before the process exits. +func notifyShutdown(err error) { +} + +func wrapListeners(proto string, ls []net.Listener) []net.Listener { + return ls +} diff --git a/cmd/dockerd/daemon_unix.go b/cmd/dockerd/daemon_unix.go index 89497f56cf..7096701fb7 100644 --- a/cmd/dockerd/daemon_unix.go +++ b/cmd/dockerd/daemon_unix.go @@ -1,4 +1,4 @@ -// +build !windows +// +build !windows,!solaris package main diff --git a/container/container_solaris.go b/container/container_solaris.go new file mode 100644 index 0000000000..ca02d8ea89 --- /dev/null +++ b/container/container_solaris.go @@ -0,0 +1,95 @@ +// +build solaris + +package container + +import ( + "os" + "path/filepath" + + "github.com/docker/docker/volume" + "github.com/docker/engine-api/types/container" +) + +// Container holds fields specific to the Solaris implementation. See +// CommonContainer for standard fields common to all containers. +type Container struct { + CommonContainer + + // fields below here are platform specific. + HostnamePath string + HostsPath string + ResolvConfPath string +} + +// ExitStatus provides exit reasons for a container. +type ExitStatus struct { + // The exit code with which the container exited. + ExitCode int +} + +// CreateDaemonEnvironment creates a new environment variable slice for this container. +func (container *Container) CreateDaemonEnvironment(linkedEnv []string) []string { + return nil +} + +func appendNetworkMounts(container *Container, volumeMounts []volume.MountPoint) ([]volume.MountPoint, error) { + return volumeMounts, nil +} + +// TrySetNetworkMount attempts to set the network mounts given a provided destination and +// the path to use for it; return true if the given destination was a network mount file +func (container *Container) TrySetNetworkMount(destination string, path string) bool { + return true +} + +// NetworkMounts returns the list of network mounts. +func (container *Container) NetworkMounts() []Mount { + var mount []Mount + return mount +} + +// CopyImagePathContent copies files in destination to the volume. +func (container *Container) CopyImagePathContent(v volume.Volume, destination string) error { + return nil +} + +// UnmountIpcMounts unmount Ipc related mounts. +func (container *Container) UnmountIpcMounts(unmount func(pth string) error) { +} + +// IpcMounts returns the list of Ipc related mounts. +func (container *Container) IpcMounts() []Mount { + return nil +} + +// UpdateContainer updates configuration of a container +func (container *Container) UpdateContainer(hostConfig *container.HostConfig) error { + return nil +} + +// UnmountVolumes explicitly unmounts volumes from the container. +func (container *Container) UnmountVolumes(forceSyscall bool, volumeEventLog func(name, action string, attributes map[string]string)) error { + return nil +} + +// TmpfsMounts returns the list of tmpfs mounts +func (container *Container) TmpfsMounts() []Mount { + var mounts []Mount + return mounts +} + +// cleanResourcePath cleans a resource path and prepares to combine with mnt path +func cleanResourcePath(path string) string { + return filepath.Join(string(os.PathSeparator), path) +} + +// BuildHostnameFile writes the container's hostname file. +func (container *Container) BuildHostnameFile() error { + return nil +} + +// canMountFS determines if the file system for the container +// can be mounted locally. A no-op on non-Windows platforms +func (container *Container) canMountFS() bool { + return true +} diff --git a/container/state_solaris.go b/container/state_solaris.go new file mode 100644 index 0000000000..02802a02a4 --- /dev/null +++ b/container/state_solaris.go @@ -0,0 +1,7 @@ +package container + +// setFromExitStatus is a platform specific helper function to set the state +// based on the ExitStatus structure. +func (s *State) setFromExitStatus(exitStatus *ExitStatus) { + s.ExitCode = exitStatus.ExitCode +} diff --git a/daemon/config_solaris.go b/daemon/config_solaris.go new file mode 100644 index 0000000000..69b98165d5 --- /dev/null +++ b/daemon/config_solaris.go @@ -0,0 +1,39 @@ +package daemon + +import ( + flag "github.com/docker/docker/pkg/mflag" +) + +var ( + defaultPidFile = "/var/run/docker.pid" + defaultGraph = "/var/lib/docker" + defaultExec = "zones" +) + +// Config defines the configuration of a docker daemon. +// These are the configuration settings that you pass +// to the docker daemon when you launch it with say: `docker -d -e lxc` +type Config struct { + CommonConfig + + // Fields below here are platform specific. + ExecRoot string `json:"exec-root,omitempty"` +} + +// bridgeConfig stores all the bridge driver specific +// configuration. +type bridgeConfig struct { + commonBridgeConfig +} + +// InstallFlags adds command-line options to the top-level flag parser for +// the current process. +// Subsequent calls to `flag.Parse` will populate config with values parsed +// from the command-line. +func (config *Config) InstallFlags(cmd *flag.FlagSet, usageFn func(string) string) { + // First handle install flags which are consistent cross-platform + config.InstallCommonFlags(cmd, usageFn) + + // Then platform-specific install flags + config.attachExperimentalFlags(cmd, usageFn) +} diff --git a/daemon/container_operations_solaris.go b/daemon/container_operations_solaris.go new file mode 100644 index 0000000000..b98faaae16 --- /dev/null +++ b/daemon/container_operations_solaris.go @@ -0,0 +1,50 @@ +// +build solaris + +package daemon + +import ( + "fmt" + + "github.com/docker/docker/container" + networktypes "github.com/docker/engine-api/types/network" + "github.com/docker/libnetwork" +) + +func (daemon *Daemon) setupLinkedContainers(container *container.Container) ([]string, error) { + return nil, nil +} + +// ConnectToNetwork connects a container to a network +func (daemon *Daemon) ConnectToNetwork(container *container.Container, idOrName string, endpointConfig *networktypes.EndpointSettings) error { + return fmt.Errorf("Solaris does not support connecting a running container to a network") +} + +// getSize returns real size & virtual size +func (daemon *Daemon) getSize(container *container.Container) (int64, int64) { + return 0, 0 +} + +// DisconnectFromNetwork disconnects a container from the network +func (daemon *Daemon) DisconnectFromNetwork(container *container.Container, n libnetwork.Network, force bool) error { + return fmt.Errorf("Solaris does not support disconnecting a running container from a network") +} + +func (daemon *Daemon) setupIpcDirs(container *container.Container) error { + return nil +} + +func (daemon *Daemon) mountVolumes(container *container.Container) error { + return nil +} + +func killProcessDirectly(container *container.Container) error { + return nil +} + +func detachMounted(path string) error { + return nil +} + +func isLinkable(child *container.Container) bool { + return false +} diff --git a/daemon/daemon.go b/daemon/daemon.go index dcaba0db65..e03e9e5c3c 100644 --- a/daemon/daemon.go +++ b/daemon/daemon.go @@ -799,7 +799,7 @@ func NewDaemon(config *Config, registryService *registry.Service, containerdRemo sysInfo := sysinfo.New(false) // Check if Devices cgroup is mounted, it is hard requirement for container security, // on Linux/FreeBSD. - if runtime.GOOS != "windows" && !sysInfo.CgroupDevicesEnabled { + if runtime.GOOS != "windows" && runtime.GOOS != "solaris" && !sysInfo.CgroupDevicesEnabled { return nil, fmt.Errorf("Devices cgroup isn't mounted") } diff --git a/daemon/daemon_solaris.go b/daemon/daemon_solaris.go new file mode 100644 index 0000000000..b43ec68481 --- /dev/null +++ b/daemon/daemon_solaris.go @@ -0,0 +1,159 @@ +// +build solaris,cgo + +package daemon + +import ( + "fmt" + + "github.com/docker/docker/container" + "github.com/docker/docker/image" + "github.com/docker/docker/layer" + "github.com/docker/docker/pkg/idtools" + "github.com/docker/docker/pkg/parsers/kernel" + "github.com/docker/docker/reference" + "github.com/docker/engine-api/types" + containertypes "github.com/docker/engine-api/types/container" + "github.com/docker/libnetwork" + nwconfig "github.com/docker/libnetwork/config" +) + +//#include +import "C" + +const ( + defaultVirtualSwitch = "Virtual Switch" + platformSupported = true + solarisMinCPUShares = 1 + solarisMaxCPUShares = 65535 +) + +func (daemon *Daemon) cleanupMountsByID(id string) error { + return nil +} + +func parseSecurityOpt(container *container.Container, config *containertypes.HostConfig) error { + return nil +} + +func setupRemappedRoot(config *Config) ([]idtools.IDMap, []idtools.IDMap, error) { + return nil, nil, nil +} + +func setupDaemonRoot(config *Config, rootDir string, rootUID, rootGID int) error { + return nil +} + +// setupInitLayer populates a directory with mountpoints suitable +// for bind-mounting dockerinit into the container. The mountpoint is simply an +// empty file at /.dockerinit +// +// This extra layer is used by all containers as the top-most ro layer. It protects +// the container from unwanted side-effects on the rw layer. +func setupInitLayer(initLayer string, rootUID, rootGID int) error { + return nil +} + +func checkKernel() error { + // solaris can rely upon checkSystem() below, we don't skew kernel versions + return nil +} + +func (daemon *Daemon) getCgroupDriver() string { + return "" +} + +func (daemon *Daemon) adaptContainerSettings(hostConfig *containertypes.HostConfig, adjustCPUShares bool) error { + return nil +} + +// verifyPlatformContainerSettings performs platform-specific validation of the +// hostconfig and config structures. +func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes.HostConfig, config *containertypes.Config, update bool) ([]string, error) { + warnings := []string{} + return warnings, nil +} + +// verifyDaemonSettings performs validation of daemon config struct +func verifyDaemonSettings(config *Config) error { + // checkSystem validates platform-specific requirements + return nil +} + +func checkSystem() error { + // check OS version for compatibility, ensure running in global zone + var err error + var id C.zoneid_t + + if id, err = C.getzoneid(); err != nil { + return fmt.Errorf("Exiting. Error getting zone id: %+v", err) + } + if int(id) != 0 { + return fmt.Errorf("Exiting because the Docker daemon is not running in the global zone") + } + + v, err := kernel.GetKernelVersion() + if kernel.CompareKernelVersion(*v, kernel.VersionInfo{Kernel: 5, Major: 12, Minor: 0}) < 0 { + return fmt.Errorf("Your Solaris kernel version: %s doesn't support Docker. Please upgrade to 5.12.0", v.String()) + } + return err +} + +// configureMaxThreads sets the Go runtime max threads threshold +// which is 90% of the kernel setting from /proc/sys/kernel/threads-max +func configureMaxThreads(config *Config) error { + return nil +} + +// configureKernelSecuritySupport configures and validate security support for the kernel +func configureKernelSecuritySupport(config *Config, driverName string) error { + return nil +} + +func (daemon *Daemon) initNetworkController(config *Config) (libnetwork.NetworkController, error) { + return nil, nil +} + +// registerLinks sets up links between containers and writes the +// configuration out for persistence. +func (daemon *Daemon) registerLinks(container *container.Container, hostConfig *containertypes.HostConfig) error { + return nil +} + +func (daemon *Daemon) cleanupMounts() error { + return nil +} + +// conditionalMountOnStart is a platform specific helper function during the +// container start to call mount. +func (daemon *Daemon) conditionalMountOnStart(container *container.Container) error { + return nil +} + +// conditionalUnmountOnCleanup is a platform specific helper function called +// during the cleanup of a container to unmount. +func (daemon *Daemon) conditionalUnmountOnCleanup(container *container.Container) error { + return daemon.Unmount(container) +} + +func restoreCustomImage(is image.Store, ls layer.Store, rs reference.Store) error { + // Solaris has no custom images to register + return nil +} + +func driverOptions(config *Config) []nwconfig.Option { + return []nwconfig.Option{} +} + +func (daemon *Daemon) stats(c *container.Container) (*types.StatsJSON, error) { + return nil, nil +} + +// setDefaultIsolation determine the default isolation mode for the +// daemon to run in. This is only applicable on Windows +func (daemon *Daemon) setDefaultIsolation() error { + return nil +} + +func rootFSToAPIType(rootfs *image.RootFS) types.RootFS { + return types.RootFS{} +} diff --git a/daemon/daemon_unsupported.go b/daemon/daemon_unsupported.go index 987528f476..cb1acf63d6 100644 --- a/daemon/daemon_unsupported.go +++ b/daemon/daemon_unsupported.go @@ -1,4 +1,4 @@ -// +build !linux,!freebsd,!windows +// +build !linux,!freebsd,!windows,!solaris package daemon diff --git a/daemon/debugtrap_unsupported.go b/daemon/debugtrap_unsupported.go index fef1bd776b..eed8222f79 100644 --- a/daemon/debugtrap_unsupported.go +++ b/daemon/debugtrap_unsupported.go @@ -1,4 +1,4 @@ -// +build !linux,!darwin,!freebsd,!windows +// +build !linux,!darwin,!freebsd,!windows,!solaris package daemon diff --git a/daemon/exec_solaris.go b/daemon/exec_solaris.go new file mode 100644 index 0000000000..7003355d91 --- /dev/null +++ b/daemon/exec_solaris.go @@ -0,0 +1,11 @@ +package daemon + +import ( + "github.com/docker/docker/container" + "github.com/docker/docker/daemon/exec" + "github.com/docker/docker/libcontainerd" +) + +func execSetPlatformOpt(c *container.Container, ec *exec.Config, p *libcontainerd.Process) error { + return nil +} diff --git a/daemon/graphdriver/driver_solaris.go b/daemon/graphdriver/driver_solaris.go new file mode 100644 index 0000000000..29719ffa4f --- /dev/null +++ b/daemon/graphdriver/driver_solaris.go @@ -0,0 +1,65 @@ +// +build solaris,cgo + +package graphdriver + +/* +#include +#include + +static inline struct statvfs *getstatfs(char *s) { + struct statvfs *buf; + int err; + buf = (struct statvfs *)malloc(sizeof(struct statvfs)); + err = statvfs(s, buf); + return buf; +} +*/ +import "C" +import ( + "path/filepath" + "unsafe" + + log "github.com/Sirupsen/logrus" +) + +const ( + // FsMagicZfs filesystem id for Zfs + FsMagicZfs = FsMagic(0x2fc12fc1) +) + +var ( + // Slice of drivers that should be used in an order + priority = []string{ + "zfs", + } + + // FsNames maps filesystem id to name of the filesystem. + FsNames = map[FsMagic]string{ + FsMagicZfs: "zfs", + } +) + +// GetFSMagic returns the filesystem id given the path. +func GetFSMagic(rootpath string) (FsMagic, error) { + return 0, nil +} + +// Mounted checks if the given path is mounted as the fs type +//Solaris supports only ZFS for now +func Mounted(fsType FsMagic, mountPath string) (bool, error) { + + cs := C.CString(filepath.Dir(mountPath)) + buf := C.getstatfs(cs) + + // on Solaris buf.f_basetype contains ['z', 'f', 's', 0 ... ] + if (buf.f_basetype[0] != 122) || (buf.f_basetype[1] != 102) || (buf.f_basetype[2] != 115) || + (buf.f_basetype[3] != 0) { + log.Debugf("[zfs] no zfs dataset found for rootdir '%s'", mountPath) + C.free(unsafe.Pointer(buf)) + return false, ErrPrerequisites + } + + C.free(unsafe.Pointer(buf)) + C.free(unsafe.Pointer(cs)) + return true, nil +} diff --git a/daemon/graphdriver/driver_unsupported.go b/daemon/graphdriver/driver_unsupported.go index b3f6857309..4a875608b0 100644 --- a/daemon/graphdriver/driver_unsupported.go +++ b/daemon/graphdriver/driver_unsupported.go @@ -1,4 +1,4 @@ -// +build !linux,!windows,!freebsd +// +build !linux,!windows,!freebsd,!solaris package graphdriver diff --git a/daemon/graphdriver/register/register_zfs.go b/daemon/graphdriver/register/register_zfs.go index 8c31c415f4..8f34e35537 100644 --- a/daemon/graphdriver/register/register_zfs.go +++ b/daemon/graphdriver/register/register_zfs.go @@ -1,4 +1,4 @@ -// +build !exclude_graphdriver_zfs,linux !exclude_graphdriver_zfs,freebsd +// +build !exclude_graphdriver_zfs,linux !exclude_graphdriver_zfs,freebsd, solaris package register diff --git a/daemon/graphdriver/zfs/zfs.go b/daemon/graphdriver/zfs/zfs.go index ffde8a545f..5ba393b282 100644 --- a/daemon/graphdriver/zfs/zfs.go +++ b/daemon/graphdriver/zfs/zfs.go @@ -1,4 +1,4 @@ -// +build linux freebsd +// +build linux freebsd solaris package zfs diff --git a/daemon/graphdriver/zfs/zfs_solaris.go b/daemon/graphdriver/zfs/zfs_solaris.go new file mode 100644 index 0000000000..0bf6c3d071 --- /dev/null +++ b/daemon/graphdriver/zfs/zfs_solaris.go @@ -0,0 +1,59 @@ +// +build solaris,cgo + +package zfs + +/* +#include +#include + +static inline struct statvfs *getstatfs(char *s) { + struct statvfs *buf; + int err; + buf = (struct statvfs *)malloc(sizeof(struct statvfs)); + err = statvfs(s, buf); + return buf; +} +*/ +import "C" +import ( + "path/filepath" + "strings" + "unsafe" + + log "github.com/Sirupsen/logrus" + "github.com/docker/docker/daemon/graphdriver" +) + +func checkRootdirFs(rootdir string) error { + + cs := C.CString(filepath.Dir(rootdir)) + buf := C.getstatfs(cs) + + // on Solaris buf.f_basetype contains ['z', 'f', 's', 0 ... ] + if (buf.f_basetype[0] != 122) || (buf.f_basetype[1] != 102) || (buf.f_basetype[2] != 115) || + (buf.f_basetype[3] != 0) { + log.Debugf("[zfs] no zfs dataset found for rootdir '%s'", rootdir) + C.free(unsafe.Pointer(buf)) + return graphdriver.ErrPrerequisites + } + + C.free(unsafe.Pointer(buf)) + C.free(unsafe.Pointer(cs)) + return nil +} + +/* rootfs is introduced to comply with the OCI spec +which states that root filesystem must be mounted at /rootfs/ instead of / +*/ +func getMountpoint(id string) string { + maxlen := 12 + + // we need to preserve filesystem suffix + suffix := strings.SplitN(id, "-", 2) + + if len(suffix) > 1 { + return filepath.Join(id[:maxlen]+"-"+suffix[1], "rootfs", "root") + } + + return filepath.Join(id[:maxlen], "rootfs", "root") +} diff --git a/daemon/graphdriver/zfs/zfs_unsupported.go b/daemon/graphdriver/zfs/zfs_unsupported.go index 643b169bc5..ce8daadaf6 100644 --- a/daemon/graphdriver/zfs/zfs_unsupported.go +++ b/daemon/graphdriver/zfs/zfs_unsupported.go @@ -1,4 +1,4 @@ -// +build !linux,!freebsd +// +build !linux,!freebsd,!solaris package zfs diff --git a/daemon/inspect_solaris.go b/daemon/inspect_solaris.go new file mode 100644 index 0000000000..2e49bef3a3 --- /dev/null +++ b/daemon/inspect_solaris.go @@ -0,0 +1,40 @@ +package daemon + +import ( + "github.com/docker/docker/api/types/backend" + "github.com/docker/docker/container" + "github.com/docker/docker/daemon/exec" + "github.com/docker/engine-api/types" +) + +// This sets platform-specific fields +func setPlatformSpecificContainerFields(container *container.Container, contJSONBase *types.ContainerJSONBase) *types.ContainerJSONBase { + return contJSONBase +} + +// containerInspectPre120 get containers for pre 1.20 APIs. +func (daemon *Daemon) containerInspectPre120(name string) (*types.ContainerJSON, error) { + return daemon.containerInspectCurrent(name, false) +} + +func addMountPoints(container *container.Container) []types.MountPoint { + mountPoints := make([]types.MountPoint, 0, len(container.MountPoints)) + for _, m := range container.MountPoints { + mountPoints = append(mountPoints, types.MountPoint{ + Name: m.Name, + Source: m.Path(), + Destination: m.Destination, + Driver: m.Driver, + RW: m.RW, + }) + } + return mountPoints +} + +func inspectExecProcessConfig(e *exec.Config) *backend.ExecProcessConfig { + return &backend.ExecProcessConfig{ + Tty: e.Tty, + Entrypoint: e.Entrypoint, + Arguments: e.Args, + } +} diff --git a/daemon/inspect_unix.go b/daemon/inspect_unix.go index 6033c02dd7..9d72d145df 100644 --- a/daemon/inspect_unix.go +++ b/daemon/inspect_unix.go @@ -1,4 +1,4 @@ -// +build !windows +// +build !windows,!solaris package daemon diff --git a/daemon/list_unix.go b/daemon/list_unix.go index 8dccbe4e89..91c9caccf4 100644 --- a/daemon/list_unix.go +++ b/daemon/list_unix.go @@ -1,4 +1,4 @@ -// +build linux freebsd +// +build linux freebsd solaris package daemon diff --git a/daemon/monitor_solaris.go b/daemon/monitor_solaris.go new file mode 100644 index 0000000000..5ccfada76a --- /dev/null +++ b/daemon/monitor_solaris.go @@ -0,0 +1,18 @@ +package daemon + +import ( + "github.com/docker/docker/container" + "github.com/docker/docker/libcontainerd" +) + +// platformConstructExitStatus returns a platform specific exit status structure +func platformConstructExitStatus(e libcontainerd.StateInfo) *container.ExitStatus { + return &container.ExitStatus{ + ExitCode: int(e.ExitCode), + } +} + +// postRunProcessing perfoms any processing needed on the container after it has stopped. +func (daemon *Daemon) postRunProcessing(container *container.Container, e libcontainerd.StateInfo) error { + return nil +} diff --git a/daemon/oci_solaris.go b/daemon/oci_solaris.go new file mode 100644 index 0000000000..05eca21169 --- /dev/null +++ b/daemon/oci_solaris.go @@ -0,0 +1,12 @@ +package daemon + +import ( + "github.com/docker/docker/container" + "github.com/docker/docker/libcontainerd" + "github.com/docker/docker/oci" +) + +func (daemon *Daemon) createSpec(c *container.Container) (*libcontainerd.Spec, error) { + s := oci.DefaultSpec() + return (*libcontainerd.Spec)(&s), nil +} diff --git a/daemon/stats_collector_solaris.go b/daemon/stats_collector_solaris.go new file mode 100644 index 0000000000..9cf9f0a94e --- /dev/null +++ b/daemon/stats_collector_solaris.go @@ -0,0 +1,34 @@ +package daemon + +import ( + "github.com/docker/docker/container" + "time" +) + +// newStatsCollector returns a new statsCollector for collection stats +// for a registered container at the specified interval. The collector allows +// non-running containers to be added and will start processing stats when +// they are started. +func (daemon *Daemon) newStatsCollector(interval time.Duration) *statsCollector { + return &statsCollector{} +} + +// statsCollector manages and provides container resource stats +type statsCollector struct { +} + +// collect registers the container with the collector and adds it to +// the event loop for collection on the specified interval returning +// a channel for the subscriber to receive on. +func (s *statsCollector) collect(c *container.Container) chan interface{} { + return nil +} + +// stopCollection closes the channels for all subscribers and removes +// the container from metrics collection. +func (s *statsCollector) stopCollection(c *container.Container) { +} + +// unsubscribe removes a specific subscriber from receiving updates for a container's stats. +func (s *statsCollector) unsubscribe(c *container.Container, ch chan interface{}) { +} diff --git a/daemon/stats_collector_unix.go b/daemon/stats_collector_unix.go index 1f016322df..f66dc2c3c7 100644 --- a/daemon/stats_collector_unix.go +++ b/daemon/stats_collector_unix.go @@ -1,4 +1,4 @@ -// +build !windows +// +build !windows,!solaris package daemon diff --git a/daemon/update_solaris.go b/daemon/update_solaris.go new file mode 100644 index 0000000000..848adae9d2 --- /dev/null +++ b/daemon/update_solaris.go @@ -0,0 +1,11 @@ +package daemon + +import ( + "github.com/docker/docker/libcontainerd" + "github.com/docker/engine-api/types/container" +) + +func toContainerdResources(resources container.Resources) libcontainerd.Resources { + var r libcontainerd.Resources + return r +} diff --git a/hack/make.sh b/hack/make.sh index e103a1aad8..3624de0e16 100755 --- a/hack/make.sh +++ b/hack/make.sh @@ -93,7 +93,7 @@ if command -v git &> /dev/null && [ -d .git ] && git rev-parse &> /dev/null; the git status --porcelain --untracked-files=no echo "#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" fi - ! BUILDTIME=$(date --rfc-3339 ns | sed -e 's/ /T/') &> /dev/null + ! BUILDTIME=$(date --rfc-3339 ns 2> /dev/null | sed -e 's/ /T/') &> /dev/null if [ -z $BUILDTIME ]; then # If using bash 3.1 which doesn't support --rfc-3389, eg Windows CI BUILDTIME=$(date -u) @@ -113,6 +113,12 @@ if [ "$AUTO_GOPATH" ]; then mkdir -p .gopath/src/"$(dirname "${DOCKER_PKG}")" ln -sf ../../../.. .gopath/src/"${DOCKER_PKG}" export GOPATH="${PWD}/.gopath:${PWD}/vendor" + + if [ "$(go env GOOS)" = 'solaris' ]; then + # sys/unix is installed outside the standard library on solaris + # TODO need to allow for version change, need to get version from go + export GOPATH="${GOPATH}:/usr/lib/gocode/1.5" + fi fi if [ ! "$GOPATH" ]; then diff --git a/layer/layer_unix.go b/layer/layer_unix.go index d77e2fc66e..776b78ac02 100644 --- a/layer/layer_unix.go +++ b/layer/layer_unix.go @@ -1,4 +1,4 @@ -// +build linux freebsd darwin openbsd +// +build linux freebsd darwin openbsd solaris package layer diff --git a/libcontainerd/client_solaris.go b/libcontainerd/client_solaris.go new file mode 100644 index 0000000000..ea8c5e1828 --- /dev/null +++ b/libcontainerd/client_solaris.go @@ -0,0 +1,56 @@ +package libcontainerd + +type client struct { + clientCommon + + // Platform specific properties below here. +} + +func (clnt *client) AddProcess(containerID, processFriendlyName string, specp Process) error { + return nil +} + +func (clnt *client) Create(containerID string, spec Spec, options ...CreateOption) (err error) { + return nil +} + +func (clnt *client) Signal(containerID string, sig int) error { + return nil +} + +func (clnt *client) Resize(containerID, processFriendlyName string, width, height int) error { + return nil +} + +func (clnt *client) Pause(containerID string) error { + return nil +} + +func (clnt *client) Resume(containerID string) error { + return nil +} + +func (clnt *client) Stats(containerID string) (*Stats, error) { + return nil, nil +} + +// Restore is the handler for restoring a container +func (clnt *client) Restore(containerID string, unusedOnWindows ...CreateOption) error { + return nil +} + +func (clnt *client) GetPidsForContainer(containerID string) ([]int, error) { + return nil, nil +} + +// Summary returns a summary of the processes running in a container. +func (clnt *client) Summary(containerID string) ([]Summary, error) { + return nil, nil +} + +// UpdateResources updates resources for a running container. +func (clnt *client) UpdateResources(containerID string, resources Resources) error { + // Updating resource isn't supported on Solaris + // but we should return nil for enabling updating container + return nil +} diff --git a/libcontainerd/container_solaris.go b/libcontainerd/container_solaris.go new file mode 100644 index 0000000000..24ab1de03b --- /dev/null +++ b/libcontainerd/container_solaris.go @@ -0,0 +1,5 @@ +package libcontainerd + +type container struct { + containerCommon +} diff --git a/libcontainerd/process_solaris.go b/libcontainerd/process_solaris.go new file mode 100644 index 0000000000..2ee9b25662 --- /dev/null +++ b/libcontainerd/process_solaris.go @@ -0,0 +1,6 @@ +package libcontainerd + +// process keeps the state for both main container process and exec process. +type process struct { + processCommon +} diff --git a/libcontainerd/remote_solaris.go b/libcontainerd/remote_solaris.go new file mode 100644 index 0000000000..bd115485ad --- /dev/null +++ b/libcontainerd/remote_solaris.go @@ -0,0 +1,25 @@ +package libcontainerd + +import "github.com/docker/docker/pkg/locker" + +type remote struct { +} + +func (r *remote) Client(b Backend) (Client, error) { + c := &client{ + clientCommon: clientCommon{ + backend: b, + containers: make(map[string]*container), + locker: locker.New(), + }, + } + return c, nil +} + +func (r *remote) Cleanup() { +} + +// New creates a fresh instance of libcontainerd remote. +func New(_ string, _ ...RemoteOption) (Remote, error) { + return &remote{}, nil +} diff --git a/libcontainerd/types_solaris.go b/libcontainerd/types_solaris.go new file mode 100644 index 0000000000..637e54300f --- /dev/null +++ b/libcontainerd/types_solaris.go @@ -0,0 +1,38 @@ +package libcontainerd + +import ( + "github.com/opencontainers/specs/specs-go" +) + +// Spec is the base configuration for the container. It specifies platform +// independent configuration. This information must be included when the +// bundle is packaged for distribution. +type Spec specs.Spec + +// Process contains information to start a specific application inside the container. +type Process struct { + // Terminal creates an interactive terminal for the container. + Terminal bool `json:"terminal"` + // Args specifies the binary and arguments for the application to execute. + Args []string `json:"args"` +} + +// Stats contains a stats properties from containerd. +type Stats struct{} + +// Summary container a container summary from containerd +type Summary struct{} + +// StateInfo contains description about the new state container has entered. +type StateInfo struct { + CommonStateInfo + + // Platform specific StateInfo +} + +// User specifies Solaris specific user and group information for the container's +// main process. +type User specs.User + +// Resources defines updatable container resource values. +type Resources struct{} diff --git a/oci/defaults_solaris.go b/oci/defaults_solaris.go new file mode 100644 index 0000000000..f3ed5c9c77 --- /dev/null +++ b/oci/defaults_solaris.go @@ -0,0 +1,11 @@ +package oci + +import ( + "github.com/opencontainers/specs/specs-go" +) + +// DefaultSpec returns default oci spec used by docker. +func DefaultSpec() specs.Spec { + s := specs.Spec{} + return s +} diff --git a/pkg/directory/directory_unix.go b/pkg/directory/directory_unix.go index dbebdd3c2c..b43c79fb85 100644 --- a/pkg/directory/directory_unix.go +++ b/pkg/directory/directory_unix.go @@ -1,4 +1,4 @@ -// +build linux freebsd +// +build linux freebsd solaris package directory diff --git a/pkg/fileutils/fileutils_solaris.go b/pkg/fileutils/fileutils_solaris.go new file mode 100644 index 0000000000..0f2cb7ab93 --- /dev/null +++ b/pkg/fileutils/fileutils_solaris.go @@ -0,0 +1,7 @@ +package fileutils + +// GetTotalUsedFds Returns the number of used File Descriptors. +// On Solaris these limits are per process and not systemwide +func GetTotalUsedFds() int { + return -1 +} diff --git a/pkg/listeners/listeners_solaris.go b/pkg/listeners/listeners_solaris.go new file mode 100644 index 0000000000..ff833e3741 --- /dev/null +++ b/pkg/listeners/listeners_solaris.go @@ -0,0 +1,31 @@ +package listeners + +import ( + "crypto/tls" + "fmt" + "net" + + "github.com/docker/go-connections/sockets" +) + +// Init creates new listeners for the server. +func Init(proto, addr, socketGroup string, tlsConfig *tls.Config) (ls []net.Listener, err error) { + switch proto { + case "tcp": + l, err := sockets.NewTCPSocket(addr, tlsConfig) + if err != nil { + return nil, err + } + ls = append(ls, l) + case "unix": + l, err := sockets.NewUnixSocket(addr, socketGroup) + if err != nil { + return nil, fmt.Errorf("can't create unix socket %s: %v", addr, err) + } + ls = append(ls, l) + default: + return nil, fmt.Errorf("Invalid protocol format: %q", proto) + } + + return +} diff --git a/pkg/listeners/listeners_unix.go b/pkg/listeners/listeners_unix.go index fddd3a8ed8..1bcae7aa3e 100644 --- a/pkg/listeners/listeners_unix.go +++ b/pkg/listeners/listeners_unix.go @@ -1,4 +1,4 @@ -// +build !windows +// +build !windows,!solaris package listeners diff --git a/pkg/mount/flags_unsupported.go b/pkg/mount/flags_unsupported.go index a90d3d1151..5564f7b3cd 100644 --- a/pkg/mount/flags_unsupported.go +++ b/pkg/mount/flags_unsupported.go @@ -1,4 +1,4 @@ -// +build !linux,!freebsd freebsd,!cgo +// +build !linux,!freebsd freebsd,!cgo solaris,!cgo package mount diff --git a/pkg/mount/mount.go b/pkg/mount/mount.go index ed7216e5c0..66ac4bf472 100644 --- a/pkg/mount/mount.go +++ b/pkg/mount/mount.go @@ -9,8 +9,8 @@ func GetMounts() ([]*Info, error) { return parseMountTable() } -// Mounted looks at /proc/self/mountinfo to determine of the specified -// mountpoint has been mounted +// Mounted determines if a specified mountpoint has been mounted. +// On Linux it looks at /proc/self/mountinfo and on Solaris at mnttab. func Mounted(mountpoint string) (bool, error) { entries, err := parseMountTable() if err != nil { diff --git a/pkg/mount/mounter_solaris.go b/pkg/mount/mounter_solaris.go new file mode 100644 index 0000000000..c684aa81fc --- /dev/null +++ b/pkg/mount/mounter_solaris.go @@ -0,0 +1,33 @@ +// +build solaris,cgo + +package mount + +import ( + "golang.org/x/sys/unix" + "unsafe" +) + +// #include +// #include +// #include +// int Mount(const char *spec, const char *dir, int mflag, +// char *fstype, char *dataptr, int datalen, char *optptr, int optlen) { +// return mount(spec, dir, mflag, fstype, dataptr, datalen, optptr, optlen); +// } +import "C" + +func mount(device, target, mType string, flag uintptr, data string) error { + spec := C.CString(device) + dir := C.CString(target) + fstype := C.CString(mType) + _, err := C.Mount(spec, dir, C.int(flag), fstype, nil, 0, nil, 0) + C.free(unsafe.Pointer(spec)) + C.free(unsafe.Pointer(dir)) + C.free(unsafe.Pointer(fstype)) + return err +} + +func unmount(target string, flag int) error { + err := unix.Unmount(target, flag) + return err +} diff --git a/pkg/mount/mounter_unsupported.go b/pkg/mount/mounter_unsupported.go index eb93365eb7..a2a3bb457f 100644 --- a/pkg/mount/mounter_unsupported.go +++ b/pkg/mount/mounter_unsupported.go @@ -1,4 +1,4 @@ -// +build !linux,!freebsd freebsd,!cgo +// +build !linux,!freebsd,!solaris freebsd,!cgo solaris,!cgo package mount diff --git a/pkg/mount/mountinfo_solaris.go b/pkg/mount/mountinfo_solaris.go new file mode 100644 index 0000000000..ad9ab57f8b --- /dev/null +++ b/pkg/mount/mountinfo_solaris.go @@ -0,0 +1,37 @@ +// +build solaris,cgo + +package mount + +/* +#include +#include +*/ +import "C" + +import ( + "fmt" +) + +func parseMountTable() ([]*Info, error) { + mnttab := C.fopen(C.CString(C.MNTTAB), C.CString("r")) + if mnttab == nil { + return nil, fmt.Errorf("Failed to open %s", C.MNTTAB) + } + + var out []*Info + var mp C.struct_mnttab + + ret := C.getmntent(mnttab, &mp) + for ret == 0 { + var mountinfo Info + mountinfo.Mountpoint = C.GoString(mp.mnt_mountp) + mountinfo.Source = C.GoString(mp.mnt_special) + mountinfo.Fstype = C.GoString(mp.mnt_fstype) + mountinfo.Opts = C.GoString(mp.mnt_mntopts) + out = append(out, &mountinfo) + ret = C.getmntent(mnttab, &mp) + } + + C.fclose(mnttab) + return out, nil +} diff --git a/pkg/mount/mountinfo_unsupported.go b/pkg/mount/mountinfo_unsupported.go index b8d9aa5c73..7fbcf19214 100644 --- a/pkg/mount/mountinfo_unsupported.go +++ b/pkg/mount/mountinfo_unsupported.go @@ -1,4 +1,4 @@ -// +build !windows,!linux,!freebsd freebsd,!cgo +// +build !windows,!linux,!freebsd,!solaris freebsd,!cgo solaris,!cgo package mount diff --git a/pkg/parsers/kernel/uname_solaris.go b/pkg/parsers/kernel/uname_solaris.go new file mode 100644 index 0000000000..49370bd3dd --- /dev/null +++ b/pkg/parsers/kernel/uname_solaris.go @@ -0,0 +1,14 @@ +package kernel + +import ( + "golang.org/x/sys/unix" +) + +func uname() (*unix.Utsname, error) { + uts := &unix.Utsname{} + + if err := unix.Uname(uts); err != nil { + return nil, err + } + return uts, nil +} diff --git a/pkg/parsers/kernel/uname_unsupported.go b/pkg/parsers/kernel/uname_unsupported.go index 79c66b3228..1da3f239fa 100644 --- a/pkg/parsers/kernel/uname_unsupported.go +++ b/pkg/parsers/kernel/uname_unsupported.go @@ -1,4 +1,4 @@ -// +build !linux +// +build !linux,!solaris package kernel diff --git a/pkg/parsers/operatingsystem/operatingsystem_solaris.go b/pkg/parsers/operatingsystem/operatingsystem_solaris.go new file mode 100644 index 0000000000..d08ad14860 --- /dev/null +++ b/pkg/parsers/operatingsystem/operatingsystem_solaris.go @@ -0,0 +1,37 @@ +// +build solaris,cgo + +package operatingsystem + +/* +#include +*/ +import "C" + +import ( + "bytes" + "errors" + "io/ioutil" +) + +var etcOsRelease = "/etc/release" + +// GetOperatingSystem gets the name of the current operating system. +func GetOperatingSystem() (string, error) { + b, err := ioutil.ReadFile(etcOsRelease) + if err != nil { + return "", err + } + if i := bytes.Index(b, []byte("\n")); i >= 0 { + b = bytes.Trim(b[:i], " ") + return string(b), nil + } + return "", errors.New("release not found") +} + +// IsContainerized returns true if we are running inside a container. +func IsContainerized() (bool, error) { + if C.getzoneid() != 0 { + return true, nil + } + return false, nil +} diff --git a/pkg/platform/architecture_freebsd.go b/pkg/platform/architecture_freebsd.go deleted file mode 100644 index 5849eccc5a..0000000000 --- a/pkg/platform/architecture_freebsd.go +++ /dev/null @@ -1,15 +0,0 @@ -package platform - -import ( - "os/exec" -) - -// runtimeArchitecture gets the name of the current architecture (x86, x86_64, …) -func runtimeArchitecture() (string, error) { - cmd := exec.Command("uname", "-m") - machine, err := cmd.Output() - if err != nil { - return "", err - } - return string(machine), nil -} diff --git a/pkg/platform/architecture_unix.go b/pkg/platform/architecture_unix.go new file mode 100644 index 0000000000..21e6a26fe2 --- /dev/null +++ b/pkg/platform/architecture_unix.go @@ -0,0 +1,18 @@ +// +build freebsd solaris + +package platform + +import ( + "os/exec" + "strings" +) + +// runtimeArchitecture get the name of the current architecture (i86pc, sun4v) +func runtimeArchitecture() (string, error) { + cmd := exec.Command("/usr/bin/uname", "-m") + machine, err := cmd.Output() + if err != nil { + return "", err + } + return strings.TrimSpace(string(machine)), nil +} diff --git a/pkg/reexec/command_freebsd.go b/pkg/reexec/command_unix.go similarity index 94% rename from pkg/reexec/command_freebsd.go rename to pkg/reexec/command_unix.go index c7f797a5fa..b70edcb316 100644 --- a/pkg/reexec/command_freebsd.go +++ b/pkg/reexec/command_unix.go @@ -1,4 +1,4 @@ -// +build freebsd +// +build freebsd solaris package reexec diff --git a/pkg/reexec/command_unsupported.go b/pkg/reexec/command_unsupported.go index ad4ea38ebb..9aed004e86 100644 --- a/pkg/reexec/command_unsupported.go +++ b/pkg/reexec/command_unsupported.go @@ -1,4 +1,4 @@ -// +build !linux,!windows,!freebsd +// +build !linux,!windows,!freebsd,!solaris package reexec diff --git a/pkg/signal/signal_solaris.go b/pkg/signal/signal_solaris.go new file mode 100644 index 0000000000..89576b9e3b --- /dev/null +++ b/pkg/signal/signal_solaris.go @@ -0,0 +1,42 @@ +package signal + +import ( + "syscall" +) + +// SignalMap is a map of Solaris signals. +// SIGINFO and SIGTHR not defined for Solaris +var SignalMap = map[string]syscall.Signal{ + "ABRT": syscall.SIGABRT, + "ALRM": syscall.SIGALRM, + "BUF": syscall.SIGBUS, + "CHLD": syscall.SIGCHLD, + "CONT": syscall.SIGCONT, + "EMT": syscall.SIGEMT, + "FPE": syscall.SIGFPE, + "HUP": syscall.SIGHUP, + "ILL": syscall.SIGILL, + "INT": syscall.SIGINT, + "IO": syscall.SIGIO, + "IOT": syscall.SIGIOT, + "KILL": syscall.SIGKILL, + "LWP": syscall.SIGLWP, + "PIPE": syscall.SIGPIPE, + "PROF": syscall.SIGPROF, + "QUIT": syscall.SIGQUIT, + "SEGV": syscall.SIGSEGV, + "STOP": syscall.SIGSTOP, + "SYS": syscall.SIGSYS, + "TERM": syscall.SIGTERM, + "TRAP": syscall.SIGTRAP, + "TSTP": syscall.SIGTSTP, + "TTIN": syscall.SIGTTIN, + "TTOU": syscall.SIGTTOU, + "URG": syscall.SIGURG, + "USR1": syscall.SIGUSR1, + "USR2": syscall.SIGUSR2, + "VTALRM": syscall.SIGVTALRM, + "WINCH": syscall.SIGWINCH, + "XCPU": syscall.SIGXCPU, + "XFSZ": syscall.SIGXFSZ, +} diff --git a/pkg/signal/signal_unsupported.go b/pkg/signal/signal_unsupported.go index 161ba27397..c592d37dfe 100644 --- a/pkg/signal/signal_unsupported.go +++ b/pkg/signal/signal_unsupported.go @@ -1,4 +1,4 @@ -// +build !linux,!darwin,!freebsd,!windows +// +build !linux,!darwin,!freebsd,!windows,!solaris package signal diff --git a/pkg/sysinfo/sysinfo_solaris.go b/pkg/sysinfo/sysinfo_solaris.go new file mode 100644 index 0000000000..75a9c9bb2d --- /dev/null +++ b/pkg/sysinfo/sysinfo_solaris.go @@ -0,0 +1,119 @@ +// +build solaris,cgo + +package sysinfo + +import ( + "bytes" + "os/exec" + "strconv" + "strings" +) + +/* +#cgo LDFLAGS: -llgrp +#include +#include +#include +int getLgrpCount() { + lgrp_cookie_t lgrpcookie = LGRP_COOKIE_NONE; + uint_t nlgrps; + + if ((lgrpcookie = lgrp_init(LGRP_VIEW_OS)) == LGRP_COOKIE_NONE) { + return -1; + } + nlgrps = lgrp_nlgrps(lgrpcookie); + return nlgrps; +} +*/ +import "C" + +// IsCPUSharesAvailable returns whether CPUShares setting is supported. +// We need FSS to be set as default scheduling class to support CPU Shares +func IsCPUSharesAvailable() bool { + cmd := exec.Command("/usr/sbin/dispadmin", "-d") + outBuf := new(bytes.Buffer) + errBuf := new(bytes.Buffer) + cmd.Stderr = errBuf + cmd.Stdout = outBuf + + if err := cmd.Run(); err != nil { + return false + } + return (strings.Contains(outBuf.String(), "FSS")) +} + +// New returns a new SysInfo, using the filesystem to detect which features +// the kernel supports. +//NOTE Solaris: If we change the below capabilities be sure +// to update verifyPlatformContainerSettings() in daemon_solaris.go +func New(quiet bool) *SysInfo { + sysInfo := &SysInfo{} + sysInfo.cgroupMemInfo = setCgroupMem(quiet) + sysInfo.cgroupCPUInfo = setCgroupCPU(quiet) + sysInfo.cgroupBlkioInfo = setCgroupBlkioInfo(quiet) + sysInfo.cgroupCpusetInfo = setCgroupCPUsetInfo(quiet) + + sysInfo.IPv4ForwardingDisabled = false + + sysInfo.AppArmor = false + + return sysInfo +} + +// setCgroupMem reads the memory information for Solaris. +func setCgroupMem(quiet bool) cgroupMemInfo { + + return cgroupMemInfo{ + MemoryLimit: true, + SwapLimit: true, + MemoryReservation: false, + OomKillDisable: false, + MemorySwappiness: false, + KernelMemory: false, + } +} + +// setCgroupCPU reads the cpu information for Solaris. +func setCgroupCPU(quiet bool) cgroupCPUInfo { + + return cgroupCPUInfo{ + CPUShares: true, + CPUCfsPeriod: false, + CPUCfsQuota: true, + } +} + +// blkio switches are not supported in Solaris. +func setCgroupBlkioInfo(quiet bool) cgroupBlkioInfo { + + return cgroupBlkioInfo{ + BlkioWeight: false, + BlkioWeightDevice: false, + } +} + +// setCgroupCPUsetInfo reads the cpuset information for Solaris. +func setCgroupCPUsetInfo(quiet bool) cgroupCpusetInfo { + + return cgroupCpusetInfo{ + Cpuset: true, + Cpus: getCPUCount(), + Mems: getLgrpCount(), + } +} + +func getCPUCount() string { + ncpus := C.sysconf(C._SC_NPROCESSORS_ONLN) + if ncpus <= 0 { + return "" + } + return strconv.FormatInt(int64(ncpus), 16) +} + +func getLgrpCount() string { + nlgrps := C.getLgrpCount() + if nlgrps <= 0 { + return "" + } + return strconv.FormatInt(int64(nlgrps), 16) +} diff --git a/pkg/system/meminfo_solaris.go b/pkg/system/meminfo_solaris.go new file mode 100644 index 0000000000..313c601b12 --- /dev/null +++ b/pkg/system/meminfo_solaris.go @@ -0,0 +1,128 @@ +// +build solaris,cgo + +package system + +import ( + "fmt" + "unsafe" +) + +// #cgo LDFLAGS: -lkstat +// #include +// #include +// #include +// #include +// #include +// #include +// struct swaptable *allocSwaptable(int num) { +// struct swaptable *st; +// struct swapent *swapent; +// st = (struct swaptable *)malloc(num * sizeof(swapent_t) + sizeof (int)); +// swapent = st->swt_ent; +// for (int i = 0; i < num; i++,swapent++) { +// swapent->ste_path = (char *)malloc(MAXPATHLEN * sizeof (char)); +// } +// st->swt_n = num; +// return st; +//} +// void freeSwaptable (struct swaptable *st) { +// struct swapent *swapent = st->swt_ent; +// for (int i = 0; i < st->swt_n; i++,swapent++) { +// free(swapent->ste_path); +// } +// free(st); +// } +// swapent_t getSwapEnt(swapent_t *ent, int i) { +// return ent[i]; +// } +// int64_t getPpKernel() { +// int64_t pp_kernel = 0; +// kstat_ctl_t *ksc; +// kstat_t *ks; +// kstat_named_t *knp; +// kid_t kid; +// +// if ((ksc = kstat_open()) == NULL) { +// return -1; +// } +// if ((ks = kstat_lookup(ksc, "unix", 0, "system_pages")) == NULL) { +// return -1; +// } +// if (((kid = kstat_read(ksc, ks, NULL)) == -1) || +// ((knp = kstat_data_lookup(ks, "pp_kernel")) == NULL)) { +// return -1; +// } +// switch (knp->data_type) { +// case KSTAT_DATA_UINT64: +// pp_kernel = knp->value.ui64; +// break; +// case KSTAT_DATA_UINT32: +// pp_kernel = knp->value.ui32; +// break; +// } +// pp_kernel *= sysconf(_SC_PAGESIZE); +// return (pp_kernel > 0 ? pp_kernel : -1); +// } +import "C" + +// Get the system memory info using sysconf same as prtconf +func getTotalMem() int64 { + pagesize := C.sysconf(C._SC_PAGESIZE) + npages := C.sysconf(C._SC_PHYS_PAGES) + return int64(pagesize * npages) +} + +func getFreeMem() int64 { + pagesize := C.sysconf(C._SC_PAGESIZE) + npages := C.sysconf(C._SC_AVPHYS_PAGES) + return int64(pagesize * npages) +} + +// ReadMemInfo retrieves memory statistics of the host system and returns a +// MemInfo type. +func ReadMemInfo() (*MemInfo, error) { + + ppKernel := C.getPpKernel() + MemTotal := getTotalMem() + MemFree := getFreeMem() + SwapTotal, SwapFree, err := getSysSwap() + + if ppKernel < 0 || MemTotal < 0 || MemFree < 0 || SwapTotal < 0 || + SwapFree < 0 { + return nil, fmt.Errorf("Error getting system memory info %v\n", err) + } + + meminfo := &MemInfo{} + // Total memory is total physical memory less than memory locked by kernel + meminfo.MemTotal = MemTotal - int64(ppKernel) + meminfo.MemFree = MemFree + meminfo.SwapTotal = SwapTotal + meminfo.SwapFree = SwapFree + + return meminfo, nil +} + +func getSysSwap() (int64, int64, error) { + var tSwap int64 + var fSwap int64 + var diskblksPerPage int64 + num, err := C.swapctl(C.SC_GETNSWP, nil) + if err != nil { + return -1, -1, err + } + st := C.allocSwaptable(num) + _, err = C.swapctl(C.SC_LIST, unsafe.Pointer(st)) + if err != nil { + C.freeSwaptable(st) + return -1, -1, err + } + + diskblksPerPage = int64(C.sysconf(C._SC_PAGESIZE) >> C.DEV_BSHIFT) + for i := 0; i < int(num); i++ { + swapent := C.getSwapEnt(&st.swt_ent[0], C.int(i)) + tSwap += int64(swapent.ste_pages) * diskblksPerPage + fSwap += int64(swapent.ste_free) * diskblksPerPage + } + C.freeSwaptable(st) + return tSwap, fSwap, nil +} diff --git a/pkg/system/meminfo_unsupported.go b/pkg/system/meminfo_unsupported.go index 82ddd30c1b..3ce019dffd 100644 --- a/pkg/system/meminfo_unsupported.go +++ b/pkg/system/meminfo_unsupported.go @@ -1,4 +1,4 @@ -// +build !linux,!windows +// +build !linux,!windows,!solaris package system diff --git a/pkg/system/stat_solaris.go b/pkg/system/stat_solaris.go index b01d08acfe..0216985a25 100644 --- a/pkg/system/stat_solaris.go +++ b/pkg/system/stat_solaris.go @@ -15,3 +15,20 @@ func fromStatT(s *syscall.Stat_t) (*StatT, error) { rdev: uint64(s.Rdev), mtim: s.Mtim}, nil } + +// FromStatT loads a system.StatT from a syscal.Stat_t. +func FromStatT(s *syscall.Stat_t) (*StatT, error) { + return fromStatT(s) +} + +// Stat takes a path to a file and returns +// a system.StatT type pertaining to that file. +// +// Throws an error if the file does not exist +func Stat(path string) (*StatT, error) { + s := &syscall.Stat_t{} + if err := syscall.Stat(path, s); err != nil { + return nil, err + } + return fromStatT(s) +} diff --git a/runconfig/hostconfig_solaris.go b/runconfig/hostconfig_solaris.go new file mode 100644 index 0000000000..6bcee7d111 --- /dev/null +++ b/runconfig/hostconfig_solaris.go @@ -0,0 +1,48 @@ +package runconfig + +import ( + "fmt" + "strings" + + "github.com/docker/engine-api/types/container" +) + +// DefaultDaemonNetworkMode returns the default network stack the daemon should +// use. +func DefaultDaemonNetworkMode() container.NetworkMode { + return container.NetworkMode("default") +} + +// IsPreDefinedNetwork indicates if a network is predefined by the daemon +func IsPreDefinedNetwork(network string) bool { + return false +} + +// ValidateNetMode ensures that the various combinations of requested +// network settings are valid. +func ValidateNetMode(c *container.Config, hc *container.HostConfig) error { + // We may not be passed a host config, such as in the case of docker commit + if hc == nil { + return nil + } + parts := strings.Split(string(hc.NetworkMode), ":") + switch mode := parts[0]; mode { + case "default", "none": + default: + return fmt.Errorf("invalid --net: %s", hc.NetworkMode) + } + return nil +} + +// ValidateIsolation performs platform specific validation of the +// isolation level in the hostconfig structure. +// This setting is currently discarded for Solaris so this is a no-op. +func ValidateIsolation(hc *container.HostConfig) error { + return nil +} + +// ValidateQoS performs platform specific validation of the QoS settings +// a disk can be limited by either Bps or IOps, but not both. +func ValidateQoS(hc *container.HostConfig) error { + return nil +} diff --git a/runconfig/hostconfig_unix.go b/runconfig/hostconfig_unix.go index 97806d6da5..9f5e289e2c 100644 --- a/runconfig/hostconfig_unix.go +++ b/runconfig/hostconfig_unix.go @@ -1,4 +1,4 @@ -// +build !windows +// +build !windows,!solaris package runconfig diff --git a/volume/local/local_unix.go b/volume/local/local_unix.go index 2e63777a19..0d288528e1 100644 --- a/volume/local/local_unix.go +++ b/volume/local/local_unix.go @@ -1,4 +1,4 @@ -// +build linux freebsd +// +build linux freebsd solaris // Package local provides the default implementation for volumes. It // is used to mount data volume containers and directories local to diff --git a/volume/store/store_unix.go b/volume/store/store_unix.go index 319c541d60..8ebc1f20c7 100644 --- a/volume/store/store_unix.go +++ b/volume/store/store_unix.go @@ -1,4 +1,4 @@ -// +build linux freebsd +// +build linux freebsd solaris package store