github.com/zhuohuang-hust/src-cbuild@v0.0.0-20230105071821-c7aab3e7c840/daemon/daemon_solaris.go (about)

     1  // +build solaris,cgo
     2  
     3  package daemon
     4  
     5  import (
     6  	"fmt"
     7  	"net"
     8  	"strconv"
     9  
    10  	"github.com/Sirupsen/logrus"
    11  	"github.com/docker/docker/api/types"
    12  	containertypes "github.com/docker/docker/api/types/container"
    13  	"github.com/docker/docker/container"
    14  	"github.com/docker/docker/image"
    15  	"github.com/docker/docker/layer"
    16  	"github.com/docker/docker/pkg/idtools"
    17  	"github.com/docker/docker/pkg/parsers/kernel"
    18  	"github.com/docker/docker/pkg/sysinfo"
    19  	"github.com/docker/docker/reference"
    20  	"github.com/docker/libnetwork"
    21  	nwconfig "github.com/docker/libnetwork/config"
    22  	"github.com/docker/libnetwork/drivers/solaris/bridge"
    23  	"github.com/docker/libnetwork/netlabel"
    24  	"github.com/docker/libnetwork/netutils"
    25  	lntypes "github.com/docker/libnetwork/types"
    26  	"github.com/opencontainers/runc/libcontainer/label"
    27  	"github.com/opencontainers/runtime-spec/specs-go"
    28  	"github.com/pkg/errors"
    29  )
    30  
    31  //#include <zone.h>
    32  import "C"
    33  
    34  const (
    35  	defaultVirtualSwitch = "Virtual Switch"
    36  	platformSupported    = true
    37  	solarisMinCPUShares  = 1
    38  	solarisMaxCPUShares  = 65535
    39  )
    40  
    41  func getMemoryResources(config containertypes.Resources) specs.CappedMemory {
    42  	memory := specs.CappedMemory{}
    43  
    44  	if config.Memory > 0 {
    45  		memory.Physical = strconv.FormatInt(config.Memory, 10)
    46  	}
    47  
    48  	if config.MemorySwap != 0 {
    49  		memory.Swap = strconv.FormatInt(config.MemorySwap, 10)
    50  	}
    51  
    52  	return memory
    53  }
    54  
    55  func getCPUResources(config containertypes.Resources) specs.CappedCPU {
    56  	cpu := specs.CappedCPU{}
    57  
    58  	if config.CpusetCpus != "" {
    59  		cpu.Ncpus = config.CpusetCpus
    60  	}
    61  
    62  	return cpu
    63  }
    64  
    65  func (daemon *Daemon) cleanupMountsByID(id string) error {
    66  	return nil
    67  }
    68  
    69  func parseSecurityOpt(container *container.Container, config *containertypes.HostConfig) error {
    70  	//Since config.SecurityOpt is specifically defined as a "List of string values to
    71  	//customize labels for MLs systems, such as SELinux"
    72  	//until we figure out how to map to Trusted Extensions
    73  	//this is being disabled for now on Solaris
    74  	var (
    75  		labelOpts []string
    76  		err       error
    77  	)
    78  
    79  	if len(config.SecurityOpt) > 0 {
    80  		return errors.New("Security options are not supported on Solaris")
    81  	}
    82  
    83  	container.ProcessLabel, container.MountLabel, err = label.InitLabels(labelOpts)
    84  	return err
    85  }
    86  
    87  func setupRemappedRoot(config *Config) ([]idtools.IDMap, []idtools.IDMap, error) {
    88  	return nil, nil, nil
    89  }
    90  
    91  func setupDaemonRoot(config *Config, rootDir string, rootUID, rootGID int) error {
    92  	return nil
    93  }
    94  
    95  func (daemon *Daemon) getLayerInit() func(string) error {
    96  	return nil
    97  }
    98  
    99  // setupInitLayer populates a directory with mountpoints suitable
   100  // for bind-mounting dockerinit into the container. The mountpoint is simply an
   101  // empty file at /.dockerinit
   102  //
   103  // This extra layer is used by all containers as the top-most ro layer. It protects
   104  // the container from unwanted side-effects on the rw layer.
   105  func setupInitLayer(initLayer string, rootUID, rootGID int) error {
   106  	return nil
   107  }
   108  
   109  func checkKernel() error {
   110  	// solaris can rely upon checkSystem() below, we don't skew kernel versions
   111  	return nil
   112  }
   113  
   114  func (daemon *Daemon) getCgroupDriver() string {
   115  	return ""
   116  }
   117  
   118  func (daemon *Daemon) adaptContainerSettings(hostConfig *containertypes.HostConfig, adjustCPUShares bool) error {
   119  	if hostConfig.CPUShares < 0 {
   120  		logrus.Warnf("Changing requested CPUShares of %d to minimum allowed of %d", hostConfig.CPUShares, solarisMinCPUShares)
   121  		hostConfig.CPUShares = solarisMinCPUShares
   122  	} else if hostConfig.CPUShares > solarisMaxCPUShares {
   123  		logrus.Warnf("Changing requested CPUShares of %d to maximum allowed of %d", hostConfig.CPUShares, solarisMaxCPUShares)
   124  		hostConfig.CPUShares = solarisMaxCPUShares
   125  	}
   126  
   127  	if hostConfig.Memory > 0 && hostConfig.MemorySwap == 0 {
   128  		// By default, MemorySwap is set to twice the size of Memory.
   129  		hostConfig.MemorySwap = hostConfig.Memory * 2
   130  	}
   131  
   132  	if hostConfig.ShmSize != 0 {
   133  		hostConfig.ShmSize = container.DefaultSHMSize
   134  	}
   135  	if hostConfig.OomKillDisable == nil {
   136  		defaultOomKillDisable := false
   137  		hostConfig.OomKillDisable = &defaultOomKillDisable
   138  	}
   139  
   140  	return nil
   141  }
   142  
   143  // UsingSystemd returns true if cli option includes native.cgroupdriver=systemd
   144  func UsingSystemd(config *Config) bool {
   145  	return false
   146  }
   147  
   148  // verifyPlatformContainerSettings performs platform-specific validation of the
   149  // hostconfig and config structures.
   150  func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes.HostConfig, config *containertypes.Config, update bool) ([]string, error) {
   151  	warnings := []string{}
   152  	sysInfo := sysinfo.New(true)
   153  	// NOTE: We do not enforce a minimum value for swap limits for zones on Solaris and
   154  	// therefore we will not do that for Docker container either.
   155  	if hostConfig.Memory > 0 && !sysInfo.MemoryLimit {
   156  		warnings = append(warnings, "Your kernel does not support memory limit capabilities. Limitation discarded.")
   157  		logrus.Warnf("Your kernel does not support memory limit capabilities. Limitation discarded.")
   158  		hostConfig.Memory = 0
   159  		hostConfig.MemorySwap = -1
   160  	}
   161  	if hostConfig.Memory > 0 && hostConfig.MemorySwap != -1 && !sysInfo.SwapLimit {
   162  		warnings = append(warnings, "Your kernel does not support swap limit capabilities, memory limited without swap.")
   163  		logrus.Warnf("Your kernel does not support swap limit capabilities, memory limited without swap.")
   164  		hostConfig.MemorySwap = -1
   165  	}
   166  	if hostConfig.Memory > 0 && hostConfig.MemorySwap > 0 && hostConfig.MemorySwap < hostConfig.Memory {
   167  		return warnings, fmt.Errorf("Minimum memoryswap limit should be larger than memory limit, see usage.")
   168  	}
   169  	// Solaris NOTE: We allow and encourage setting the swap without setting the memory limit.
   170  
   171  	if hostConfig.MemorySwappiness != nil && *hostConfig.MemorySwappiness != -1 && !sysInfo.MemorySwappiness {
   172  		warnings = append(warnings, "Your kernel does not support memory swappiness capabilities, memory swappiness discarded.")
   173  		logrus.Warnf("Your kernel does not support memory swappiness capabilities, memory swappiness discarded.")
   174  		hostConfig.MemorySwappiness = nil
   175  	}
   176  	if hostConfig.MemoryReservation > 0 && !sysInfo.MemoryReservation {
   177  		warnings = append(warnings, "Your kernel does not support memory soft limit capabilities. Limitation discarded.")
   178  		logrus.Warnf("Your kernel does not support memory soft limit capabilities. Limitation discarded.")
   179  		hostConfig.MemoryReservation = 0
   180  	}
   181  	if hostConfig.Memory > 0 && hostConfig.MemoryReservation > 0 && hostConfig.Memory < hostConfig.MemoryReservation {
   182  		return warnings, fmt.Errorf("Minimum memory limit should be larger than memory reservation limit, see usage.")
   183  	}
   184  	if hostConfig.KernelMemory > 0 && !sysInfo.KernelMemory {
   185  		warnings = append(warnings, "Your kernel does not support kernel memory limit capabilities. Limitation discarded.")
   186  		logrus.Warnf("Your kernel does not support kernel memory limit capabilities. Limitation discarded.")
   187  		hostConfig.KernelMemory = 0
   188  	}
   189  	if hostConfig.CPUShares != 0 && !sysInfo.CPUShares {
   190  		warnings = append(warnings, "Your kernel does not support CPU shares. Shares discarded.")
   191  		logrus.Warnf("Your kernel does not support CPU shares. Shares discarded.")
   192  		hostConfig.CPUShares = 0
   193  	}
   194  	if hostConfig.CPUShares < 0 {
   195  		warnings = append(warnings, "Invalid CPUShares value. Must be positive. Discarding.")
   196  		logrus.Warnf("Invalid CPUShares value. Must be positive. Discarding.")
   197  		hostConfig.CPUQuota = 0
   198  	}
   199  	if hostConfig.CPUShares > 0 && !sysinfo.IsCPUSharesAvailable() {
   200  		warnings = append(warnings, "Global zone default scheduling class not FSS. Discarding shares.")
   201  		logrus.Warnf("Global zone default scheduling class not FSS. Discarding shares.")
   202  		hostConfig.CPUShares = 0
   203  	}
   204  
   205  	// Solaris NOTE: Linux does not do negative checking for CPUShares and Quota here. But it makes sense to.
   206  	if hostConfig.CPUPeriod > 0 && !sysInfo.CPUCfsPeriod {
   207  		warnings = append(warnings, "Your kernel does not support CPU cfs period. Period discarded.")
   208  		logrus.Warnf("Your kernel does not support CPU cfs period. Period discarded.")
   209  		if hostConfig.CPUQuota > 0 {
   210  			warnings = append(warnings, "Quota will be applied on default period, not period specified.")
   211  			logrus.Warnf("Quota will be applied on default period, not period specified.")
   212  		}
   213  		hostConfig.CPUPeriod = 0
   214  	}
   215  	if hostConfig.CPUQuota != 0 && !sysInfo.CPUCfsQuota {
   216  		warnings = append(warnings, "Your kernel does not support CPU cfs quota. Quota discarded.")
   217  		logrus.Warnf("Your kernel does not support CPU cfs quota. Quota discarded.")
   218  		hostConfig.CPUQuota = 0
   219  	}
   220  	if hostConfig.CPUQuota < 0 {
   221  		warnings = append(warnings, "Invalid CPUQuota value. Must be positive. Discarding.")
   222  		logrus.Warnf("Invalid CPUQuota value. Must be positive. Discarding.")
   223  		hostConfig.CPUQuota = 0
   224  	}
   225  	if (hostConfig.CpusetCpus != "" || hostConfig.CpusetMems != "") && !sysInfo.Cpuset {
   226  		warnings = append(warnings, "Your kernel does not support cpuset. Cpuset discarded.")
   227  		logrus.Warnf("Your kernel does not support cpuset. Cpuset discarded.")
   228  		hostConfig.CpusetCpus = ""
   229  		hostConfig.CpusetMems = ""
   230  	}
   231  	cpusAvailable, err := sysInfo.IsCpusetCpusAvailable(hostConfig.CpusetCpus)
   232  	if err != nil {
   233  		return warnings, fmt.Errorf("Invalid value %s for cpuset cpus.", hostConfig.CpusetCpus)
   234  	}
   235  	if !cpusAvailable {
   236  		return warnings, fmt.Errorf("Requested CPUs are not available - requested %s, available: %s.", hostConfig.CpusetCpus, sysInfo.Cpus)
   237  	}
   238  	memsAvailable, err := sysInfo.IsCpusetMemsAvailable(hostConfig.CpusetMems)
   239  	if err != nil {
   240  		return warnings, fmt.Errorf("Invalid value %s for cpuset mems.", hostConfig.CpusetMems)
   241  	}
   242  	if !memsAvailable {
   243  		return warnings, fmt.Errorf("Requested memory nodes are not available - requested %s, available: %s.", hostConfig.CpusetMems, sysInfo.Mems)
   244  	}
   245  	if hostConfig.BlkioWeight > 0 && !sysInfo.BlkioWeight {
   246  		warnings = append(warnings, "Your kernel does not support Block I/O weight. Weight discarded.")
   247  		logrus.Warnf("Your kernel does not support Block I/O weight. Weight discarded.")
   248  		hostConfig.BlkioWeight = 0
   249  	}
   250  	if hostConfig.OomKillDisable != nil && !sysInfo.OomKillDisable {
   251  		*hostConfig.OomKillDisable = false
   252  		// Don't warn; this is the default setting but only applicable to Linux
   253  	}
   254  
   255  	if sysInfo.IPv4ForwardingDisabled {
   256  		warnings = append(warnings, "IPv4 forwarding is disabled. Networking will not work.")
   257  		logrus.Warnf("IPv4 forwarding is disabled. Networking will not work")
   258  	}
   259  
   260  	// Solaris NOTE: We do not allow setting Linux specific options, so check and warn for all of them.
   261  
   262  	if hostConfig.CapAdd != nil || hostConfig.CapDrop != nil {
   263  		warnings = append(warnings, "Adding or dropping kernel capabilities unsupported on Solaris.Discarding capabilities lists.")
   264  		logrus.Warnf("Adding or dropping kernel capabilities unsupported on Solaris.Discarding capabilities lists.")
   265  		hostConfig.CapAdd = nil
   266  		hostConfig.CapDrop = nil
   267  	}
   268  
   269  	if hostConfig.GroupAdd != nil {
   270  		warnings = append(warnings, "Additional groups unsupported on Solaris.Discarding groups lists.")
   271  		logrus.Warnf("Additional groups unsupported on Solaris.Discarding groups lists.")
   272  		hostConfig.GroupAdd = nil
   273  	}
   274  
   275  	if hostConfig.IpcMode != "" {
   276  		warnings = append(warnings, "IPC namespace assignment unsupported on Solaris.Discarding IPC setting.")
   277  		logrus.Warnf("IPC namespace assignment unsupported on Solaris.Discarding IPC setting.")
   278  		hostConfig.IpcMode = ""
   279  	}
   280  
   281  	if hostConfig.PidMode != "" {
   282  		warnings = append(warnings, "PID namespace setting  unsupported on Solaris. Running container in host PID namespace.")
   283  		logrus.Warnf("PID namespace setting  unsupported on Solaris. Running container in host PID namespace.")
   284  		hostConfig.PidMode = ""
   285  	}
   286  
   287  	if hostConfig.Privileged {
   288  		warnings = append(warnings, "Privileged mode unsupported on Solaris. Discarding privileged mode setting.")
   289  		logrus.Warnf("Privileged mode unsupported on Solaris. Discarding privileged mode setting.")
   290  		hostConfig.Privileged = false
   291  	}
   292  
   293  	if hostConfig.UTSMode != "" {
   294  		warnings = append(warnings, "UTS namespace assignment unsupported on Solaris.Discarding UTS setting.")
   295  		logrus.Warnf("UTS namespace assignment unsupported on Solaris.Discarding UTS setting.")
   296  		hostConfig.UTSMode = ""
   297  	}
   298  
   299  	if hostConfig.CgroupParent != "" {
   300  		warnings = append(warnings, "Specifying Cgroup parent unsupported on Solaris. Discarding cgroup parent setting.")
   301  		logrus.Warnf("Specifying Cgroup parent unsupported on Solaris. Discarding cgroup parent setting.")
   302  		hostConfig.CgroupParent = ""
   303  	}
   304  
   305  	if hostConfig.Ulimits != nil {
   306  		warnings = append(warnings, "Specifying ulimits unsupported on Solaris. Discarding ulimits setting.")
   307  		logrus.Warnf("Specifying ulimits unsupported on Solaris. Discarding ulimits setting.")
   308  		hostConfig.Ulimits = nil
   309  	}
   310  
   311  	return warnings, nil
   312  }
   313  
   314  // platformReload update configuration with platform specific options
   315  func (daemon *Daemon) platformReload(config *Config) map[string]string {
   316  	return map[string]string{}
   317  }
   318  
   319  // verifyDaemonSettings performs validation of daemon config struct
   320  func verifyDaemonSettings(config *Config) error {
   321  
   322  	if config.DefaultRuntime == "" {
   323  		config.DefaultRuntime = stockRuntimeName
   324  	}
   325  	if config.Runtimes == nil {
   326  		config.Runtimes = make(map[string]types.Runtime)
   327  	}
   328  	stockRuntimeOpts := []string{}
   329  	config.Runtimes[stockRuntimeName] = types.Runtime{Path: DefaultRuntimeBinary, Args: stockRuntimeOpts}
   330  
   331  	// checkSystem validates platform-specific requirements
   332  	return nil
   333  }
   334  
   335  func checkSystem() error {
   336  	// check OS version for compatibility, ensure running in global zone
   337  	var err error
   338  	var id C.zoneid_t
   339  
   340  	if id, err = C.getzoneid(); err != nil {
   341  		return fmt.Errorf("Exiting. Error getting zone id: %+v", err)
   342  	}
   343  	if int(id) != 0 {
   344  		return fmt.Errorf("Exiting because the Docker daemon is not running in the global zone")
   345  	}
   346  
   347  	v, err := kernel.GetKernelVersion()
   348  	if kernel.CompareKernelVersion(*v, kernel.VersionInfo{Kernel: 5, Major: 12, Minor: 0}) < 0 {
   349  		return fmt.Errorf("Your Solaris kernel version: %s doesn't support Docker. Please upgrade to 5.12.0", v.String())
   350  	}
   351  	return err
   352  }
   353  
   354  // configureMaxThreads sets the Go runtime max threads threshold
   355  // which is 90% of the kernel setting from /proc/sys/kernel/threads-max
   356  func configureMaxThreads(config *Config) error {
   357  	return nil
   358  }
   359  
   360  // configureKernelSecuritySupport configures and validate security support for the kernel
   361  func configureKernelSecuritySupport(config *Config, driverName string) error {
   362  	return nil
   363  }
   364  
   365  func (daemon *Daemon) initNetworkController(config *Config, activeSandboxes map[string]interface{}) (libnetwork.NetworkController, error) {
   366  	netOptions, err := daemon.networkOptions(config, daemon.PluginStore, activeSandboxes)
   367  	if err != nil {
   368  		return nil, err
   369  	}
   370  
   371  	controller, err := libnetwork.New(netOptions...)
   372  	if err != nil {
   373  		return nil, fmt.Errorf("error obtaining controller instance: %v", err)
   374  	}
   375  
   376  	// Initialize default network on "null"
   377  	if _, err := controller.NewNetwork("null", "none", "", libnetwork.NetworkOptionPersist(false)); err != nil {
   378  		return nil, fmt.Errorf("Error creating default 'null' network: %v", err)
   379  	}
   380  
   381  	if !config.DisableBridge {
   382  		// Initialize default driver "bridge"
   383  		if err := initBridgeDriver(controller, config); err != nil {
   384  			return nil, err
   385  		}
   386  	}
   387  
   388  	return controller, nil
   389  }
   390  
   391  func initBridgeDriver(controller libnetwork.NetworkController, config *Config) error {
   392  	if n, err := controller.NetworkByName("bridge"); err == nil {
   393  		if err = n.Delete(); err != nil {
   394  			return fmt.Errorf("could not delete the default bridge network: %v", err)
   395  		}
   396  	}
   397  
   398  	bridgeName := bridge.DefaultBridgeName
   399  	if config.bridgeConfig.Iface != "" {
   400  		bridgeName = config.bridgeConfig.Iface
   401  	}
   402  	netOption := map[string]string{
   403  		bridge.BridgeName:    bridgeName,
   404  		bridge.DefaultBridge: strconv.FormatBool(true),
   405  		netlabel.DriverMTU:   strconv.Itoa(config.Mtu),
   406  		bridge.EnableICC:     strconv.FormatBool(config.bridgeConfig.InterContainerCommunication),
   407  	}
   408  
   409  	// --ip processing
   410  	if config.bridgeConfig.DefaultIP != nil {
   411  		netOption[bridge.DefaultBindingIP] = config.bridgeConfig.DefaultIP.String()
   412  	}
   413  
   414  	var ipamV4Conf *libnetwork.IpamConf
   415  
   416  	ipamV4Conf = &libnetwork.IpamConf{AuxAddresses: make(map[string]string)}
   417  
   418  	nwList, _, err := netutils.ElectInterfaceAddresses(bridgeName)
   419  	if err != nil {
   420  		return errors.Wrap(err, "list bridge addresses failed")
   421  	}
   422  
   423  	nw := nwList[0]
   424  	if len(nwList) > 1 && config.bridgeConfig.FixedCIDR != "" {
   425  		_, fCIDR, err := net.ParseCIDR(config.bridgeConfig.FixedCIDR)
   426  		if err != nil {
   427  			return errors.Wrap(err, "parse CIDR failed")
   428  		}
   429  		// Iterate through in case there are multiple addresses for the bridge
   430  		for _, entry := range nwList {
   431  			if fCIDR.Contains(entry.IP) {
   432  				nw = entry
   433  				break
   434  			}
   435  		}
   436  	}
   437  
   438  	ipamV4Conf.PreferredPool = lntypes.GetIPNetCanonical(nw).String()
   439  	hip, _ := lntypes.GetHostPartIP(nw.IP, nw.Mask)
   440  	if hip.IsGlobalUnicast() {
   441  		ipamV4Conf.Gateway = nw.IP.String()
   442  	}
   443  
   444  	if config.bridgeConfig.IP != "" {
   445  		ipamV4Conf.PreferredPool = config.bridgeConfig.IP
   446  		ip, _, err := net.ParseCIDR(config.bridgeConfig.IP)
   447  		if err != nil {
   448  			return err
   449  		}
   450  		ipamV4Conf.Gateway = ip.String()
   451  	} else if bridgeName == bridge.DefaultBridgeName && ipamV4Conf.PreferredPool != "" {
   452  		logrus.Infof("Default bridge (%s) is assigned with an IP address %s. Daemon option --bip can be used to set a preferred IP address", bridgeName, ipamV4Conf.PreferredPool)
   453  	}
   454  
   455  	if config.bridgeConfig.FixedCIDR != "" {
   456  		_, fCIDR, err := net.ParseCIDR(config.bridgeConfig.FixedCIDR)
   457  		if err != nil {
   458  			return err
   459  		}
   460  
   461  		ipamV4Conf.SubPool = fCIDR.String()
   462  	}
   463  
   464  	if config.bridgeConfig.DefaultGatewayIPv4 != nil {
   465  		ipamV4Conf.AuxAddresses["DefaultGatewayIPv4"] = config.bridgeConfig.DefaultGatewayIPv4.String()
   466  	}
   467  
   468  	v4Conf := []*libnetwork.IpamConf{ipamV4Conf}
   469  	v6Conf := []*libnetwork.IpamConf{}
   470  
   471  	// Initialize default network on "bridge" with the same name
   472  	_, err = controller.NewNetwork("bridge", "bridge", "",
   473  		libnetwork.NetworkOptionDriverOpts(netOption),
   474  		libnetwork.NetworkOptionIpam("default", "", v4Conf, v6Conf, nil),
   475  		libnetwork.NetworkOptionDeferIPv6Alloc(false))
   476  	if err != nil {
   477  		return fmt.Errorf("Error creating default 'bridge' network: %v", err)
   478  	}
   479  	return nil
   480  }
   481  
   482  // registerLinks sets up links between containers and writes the
   483  // configuration out for persistence.
   484  func (daemon *Daemon) registerLinks(container *container.Container, hostConfig *containertypes.HostConfig) error {
   485  	return nil
   486  }
   487  
   488  func (daemon *Daemon) cleanupMounts() error {
   489  	return nil
   490  }
   491  
   492  // conditionalMountOnStart is a platform specific helper function during the
   493  // container start to call mount.
   494  func (daemon *Daemon) conditionalMountOnStart(container *container.Container) error {
   495  	return daemon.Mount(container)
   496  }
   497  
   498  // conditionalUnmountOnCleanup is a platform specific helper function called
   499  // during the cleanup of a container to unmount.
   500  func (daemon *Daemon) conditionalUnmountOnCleanup(container *container.Container) error {
   501  	return daemon.Unmount(container)
   502  }
   503  
   504  func restoreCustomImage(is image.Store, ls layer.Store, rs reference.Store) error {
   505  	// Solaris has no custom images to register
   506  	return nil
   507  }
   508  
   509  func driverOptions(config *Config) []nwconfig.Option {
   510  	return []nwconfig.Option{}
   511  }
   512  
   513  func (daemon *Daemon) stats(c *container.Container) (*types.StatsJSON, error) {
   514  	return nil, nil
   515  }
   516  
   517  // setDefaultIsolation determine the default isolation mode for the
   518  // daemon to run in. This is only applicable on Windows
   519  func (daemon *Daemon) setDefaultIsolation() error {
   520  	return nil
   521  }
   522  
   523  func rootFSToAPIType(rootfs *image.RootFS) types.RootFS {
   524  	return types.RootFS{}
   525  }
   526  
   527  func setupDaemonProcess(config *Config) error {
   528  	return nil
   529  }
   530  
   531  func (daemon *Daemon) setupSeccompProfile() error {
   532  	return nil
   533  }