Browse Source

Get the Docker Engine to build clean on Solaris

Signed-off-by: Amit Krishnan <krish.amit@gmail.com>
Amit Krishnan 9 years ago
parent
commit
86d8758e2b
60 changed files with 1380 additions and 43 deletions
  1. 74 0
      cmd/dockerd/daemon_solaris.go
  2. 1 1
      cmd/dockerd/daemon_unix.go
  3. 95 0
      container/container_solaris.go
  4. 7 0
      container/state_solaris.go
  5. 39 0
      daemon/config_solaris.go
  6. 50 0
      daemon/container_operations_solaris.go
  7. 1 1
      daemon/daemon.go
  8. 159 0
      daemon/daemon_solaris.go
  9. 1 1
      daemon/daemon_unsupported.go
  10. 1 1
      daemon/debugtrap_unsupported.go
  11. 11 0
      daemon/exec_solaris.go
  12. 65 0
      daemon/graphdriver/driver_solaris.go
  13. 1 1
      daemon/graphdriver/driver_unsupported.go
  14. 1 1
      daemon/graphdriver/register/register_zfs.go
  15. 1 1
      daemon/graphdriver/zfs/zfs.go
  16. 59 0
      daemon/graphdriver/zfs/zfs_solaris.go
  17. 1 1
      daemon/graphdriver/zfs/zfs_unsupported.go
  18. 40 0
      daemon/inspect_solaris.go
  19. 1 1
      daemon/inspect_unix.go
  20. 1 1
      daemon/list_unix.go
  21. 18 0
      daemon/monitor_solaris.go
  22. 12 0
      daemon/oci_solaris.go
  23. 34 0
      daemon/stats_collector_solaris.go
  24. 1 1
      daemon/stats_collector_unix.go
  25. 11 0
      daemon/update_solaris.go
  26. 7 1
      hack/make.sh
  27. 1 1
      layer/layer_unix.go
  28. 56 0
      libcontainerd/client_solaris.go
  29. 5 0
      libcontainerd/container_solaris.go
  30. 6 0
      libcontainerd/process_solaris.go
  31. 25 0
      libcontainerd/remote_solaris.go
  32. 38 0
      libcontainerd/types_solaris.go
  33. 11 0
      oci/defaults_solaris.go
  34. 1 1
      pkg/directory/directory_unix.go
  35. 7 0
      pkg/fileutils/fileutils_solaris.go
  36. 31 0
      pkg/listeners/listeners_solaris.go
  37. 1 1
      pkg/listeners/listeners_unix.go
  38. 1 1
      pkg/mount/flags_unsupported.go
  39. 2 2
      pkg/mount/mount.go
  40. 33 0
      pkg/mount/mounter_solaris.go
  41. 1 1
      pkg/mount/mounter_unsupported.go
  42. 37 0
      pkg/mount/mountinfo_solaris.go
  43. 1 1
      pkg/mount/mountinfo_unsupported.go
  44. 14 0
      pkg/parsers/kernel/uname_solaris.go
  45. 1 1
      pkg/parsers/kernel/uname_unsupported.go
  46. 37 0
      pkg/parsers/operatingsystem/operatingsystem_solaris.go
  47. 0 15
      pkg/platform/architecture_freebsd.go
  48. 18 0
      pkg/platform/architecture_unix.go
  49. 1 1
      pkg/reexec/command_unix.go
  50. 1 1
      pkg/reexec/command_unsupported.go
  51. 42 0
      pkg/signal/signal_solaris.go
  52. 1 1
      pkg/signal/signal_unsupported.go
  53. 119 0
      pkg/sysinfo/sysinfo_solaris.go
  54. 128 0
      pkg/system/meminfo_solaris.go
  55. 1 1
      pkg/system/meminfo_unsupported.go
  56. 17 0
      pkg/system/stat_solaris.go
  57. 48 0
      runconfig/hostconfig_solaris.go
  58. 1 1
      runconfig/hostconfig_unix.go
  59. 1 1
      volume/local/local_unix.go
  60. 1 1
      volume/store/store_unix.go

+ 74 - 0
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
+}

+ 1 - 1
cmd/dockerd/daemon_unix.go

@@ -1,4 +1,4 @@
-// +build !windows
+// +build !windows,!solaris
 
 package main
 

+ 95 - 0
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
+}

+ 7 - 0
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
+}

+ 39 - 0
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)
+}

+ 50 - 0
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
+}

+ 1 - 1
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")
 	}
 

+ 159 - 0
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 <zone.h>
+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{}
+}

+ 1 - 1
daemon/daemon_unsupported.go

@@ -1,4 +1,4 @@
-// +build !linux,!freebsd,!windows
+// +build !linux,!freebsd,!windows,!solaris
 
 package daemon
 

+ 1 - 1
daemon/debugtrap_unsupported.go

@@ -1,4 +1,4 @@
-// +build !linux,!darwin,!freebsd,!windows
+// +build !linux,!darwin,!freebsd,!windows,!solaris
 
 package daemon
 

+ 11 - 0
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
+}

+ 65 - 0
daemon/graphdriver/driver_solaris.go

@@ -0,0 +1,65 @@
+// +build solaris,cgo
+
+package graphdriver
+
+/*
+#include <sys/statvfs.h>
+#include <stdlib.h>
+
+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
+}

+ 1 - 1
daemon/graphdriver/driver_unsupported.go

@@ -1,4 +1,4 @@
-// +build !linux,!windows,!freebsd
+// +build !linux,!windows,!freebsd,!solaris
 
 package graphdriver
 

+ 1 - 1
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
 

+ 1 - 1
daemon/graphdriver/zfs/zfs.go

@@ -1,4 +1,4 @@
-// +build linux freebsd
+// +build linux freebsd solaris
 
 package zfs
 

+ 59 - 0
daemon/graphdriver/zfs/zfs_solaris.go

@@ -0,0 +1,59 @@
+// +build solaris,cgo
+
+package zfs
+
+/*
+#include <sys/statvfs.h>
+#include <stdlib.h>
+
+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 <CID>/rootfs/ instead of <CID>/
+*/
+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")
+}

+ 1 - 1
daemon/graphdriver/zfs/zfs_unsupported.go

@@ -1,4 +1,4 @@
-// +build !linux,!freebsd
+// +build !linux,!freebsd,!solaris
 
 package zfs
 

+ 40 - 0
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,
+	}
+}

+ 1 - 1
daemon/inspect_unix.go

@@ -1,4 +1,4 @@
-// +build !windows
+// +build !windows,!solaris
 
 package daemon
 

+ 1 - 1
daemon/list_unix.go

@@ -1,4 +1,4 @@
-// +build linux freebsd
+// +build linux freebsd solaris
 
 package daemon
 

+ 18 - 0
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
+}

+ 12 - 0
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
+}

+ 34 - 0
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{}) {
+}

+ 1 - 1
daemon/stats_collector_unix.go

@@ -1,4 +1,4 @@
-// +build !windows
+// +build !windows,!solaris
 
 package daemon
 

+ 11 - 0
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
+}

+ 7 - 1
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

+ 1 - 1
layer/layer_unix.go

@@ -1,4 +1,4 @@
-// +build linux freebsd darwin openbsd
+// +build linux freebsd darwin openbsd solaris
 
 package layer
 

+ 56 - 0
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
+}

+ 5 - 0
libcontainerd/container_solaris.go

@@ -0,0 +1,5 @@
+package libcontainerd
+
+type container struct {
+	containerCommon
+}

+ 6 - 0
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
+}

+ 25 - 0
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
+}

+ 38 - 0
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{}

+ 11 - 0
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
+}

+ 1 - 1
pkg/directory/directory_unix.go

@@ -1,4 +1,4 @@
-// +build linux freebsd
+// +build linux freebsd solaris
 
 package directory
 

+ 7 - 0
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
+}

+ 31 - 0
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
+}

+ 1 - 1
pkg/listeners/listeners_unix.go

@@ -1,4 +1,4 @@
-// +build !windows
+// +build !windows,!solaris
 
 package listeners
 

+ 1 - 1
pkg/mount/flags_unsupported.go

@@ -1,4 +1,4 @@
-// +build !linux,!freebsd freebsd,!cgo
+// +build !linux,!freebsd freebsd,!cgo solaris,!cgo
 
 package mount
 

+ 2 - 2
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 {

+ 33 - 0
pkg/mount/mounter_solaris.go

@@ -0,0 +1,33 @@
+// +build solaris,cgo
+
+package mount
+
+import (
+	"golang.org/x/sys/unix"
+	"unsafe"
+)
+
+// #include <stdlib.h>
+// #include <stdio.h>
+// #include <sys/mount.h>
+// 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
+}

+ 1 - 1
pkg/mount/mounter_unsupported.go

@@ -1,4 +1,4 @@
-// +build !linux,!freebsd freebsd,!cgo
+// +build !linux,!freebsd,!solaris freebsd,!cgo solaris,!cgo
 
 package mount
 

+ 37 - 0
pkg/mount/mountinfo_solaris.go

@@ -0,0 +1,37 @@
+// +build solaris,cgo
+
+package mount
+
+/*
+#include <stdio.h>
+#include <sys/mnttab.h>
+*/
+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
+}

+ 1 - 1
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
 

+ 14 - 0
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
+}

+ 1 - 1
pkg/parsers/kernel/uname_unsupported.go

@@ -1,4 +1,4 @@
-// +build !linux
+// +build !linux,!solaris
 
 package kernel
 

+ 37 - 0
pkg/parsers/operatingsystem/operatingsystem_solaris.go

@@ -0,0 +1,37 @@
+// +build solaris,cgo
+
+package operatingsystem
+
+/*
+#include <zone.h>
+*/
+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
+}

+ 0 - 15
pkg/platform/architecture_freebsd.go

@@ -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
-}

+ 18 - 0
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
+}

+ 1 - 1
pkg/reexec/command_freebsd.go → pkg/reexec/command_unix.go

@@ -1,4 +1,4 @@
-// +build freebsd
+// +build freebsd solaris
 
 package reexec
 

+ 1 - 1
pkg/reexec/command_unsupported.go

@@ -1,4 +1,4 @@
-// +build !linux,!windows,!freebsd
+// +build !linux,!windows,!freebsd,!solaris
 
 package reexec
 

+ 42 - 0
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,
+}

+ 1 - 1
pkg/signal/signal_unsupported.go

@@ -1,4 +1,4 @@
-// +build !linux,!darwin,!freebsd,!windows
+// +build !linux,!darwin,!freebsd,!windows,!solaris
 
 package signal
 

+ 119 - 0
pkg/sysinfo/sysinfo_solaris.go

@@ -0,0 +1,119 @@
+// +build solaris,cgo
+
+package sysinfo
+
+import (
+	"bytes"
+	"os/exec"
+	"strconv"
+	"strings"
+)
+
+/*
+#cgo LDFLAGS: -llgrp
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/lgrp_user.h>
+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)
+}

+ 128 - 0
pkg/system/meminfo_solaris.go

@@ -0,0 +1,128 @@
+// +build solaris,cgo
+
+package system
+
+import (
+	"fmt"
+	"unsafe"
+)
+
+// #cgo LDFLAGS: -lkstat
+// #include <unistd.h>
+// #include <stdlib.h>
+// #include <stdio.h>
+// #include <kstat.h>
+// #include <sys/swap.h>
+// #include <sys/param.h>
+// 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
+}

+ 1 - 1
pkg/system/meminfo_unsupported.go

@@ -1,4 +1,4 @@
-// +build !linux,!windows
+// +build !linux,!windows,!solaris
 
 package system
 

+ 17 - 0
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)
+}

+ 48 - 0
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
+}

+ 1 - 1
runconfig/hostconfig_unix.go

@@ -1,4 +1,4 @@
-// +build !windows
+// +build !windows,!solaris
 
 package runconfig
 

+ 1 - 1
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

+ 1 - 1
volume/store/store_unix.go

@@ -1,4 +1,4 @@
-// +build linux freebsd
+// +build linux freebsd solaris
 
 package store