mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00

containers may specify these cgroup values at runtime. This will allow processes to change their priority to real-time within the container when CONFIG_RT_GROUP_SCHED is enabled in the kernel. See #22380. Also added sanity checks for the new --cpu-rt-runtime and --cpu-rt-period flags to ensure that that the kernel supports these features and that runtime is not greater than period. Daemon will support a --cpu-rt-runtime flag to initialize the parent cgroup on startup, this prevents the administrator from alotting runtime to docker after each restart. There are additional checks that could be added but maybe too far? Check parent cgroups to ensure values are <= parent, inspecting rtprio ulimit and issuing a warning. Signed-off-by: Erik St. Martin <alakriti@gmail.com>
109 lines
3.3 KiB
Go
109 lines
3.3 KiB
Go
package runconfig
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
|
|
"github.com/docker/docker/api/types/container"
|
|
networktypes "github.com/docker/docker/api/types/network"
|
|
"github.com/docker/docker/pkg/sysinfo"
|
|
"github.com/docker/docker/volume"
|
|
)
|
|
|
|
// ContainerDecoder implements httputils.ContainerDecoder
|
|
// calling DecodeContainerConfig.
|
|
type ContainerDecoder struct{}
|
|
|
|
// DecodeConfig makes ContainerDecoder to implement httputils.ContainerDecoder
|
|
func (r ContainerDecoder) DecodeConfig(src io.Reader) (*container.Config, *container.HostConfig, *networktypes.NetworkingConfig, error) {
|
|
return DecodeContainerConfig(src)
|
|
}
|
|
|
|
// DecodeHostConfig makes ContainerDecoder to implement httputils.ContainerDecoder
|
|
func (r ContainerDecoder) DecodeHostConfig(src io.Reader) (*container.HostConfig, error) {
|
|
return DecodeHostConfig(src)
|
|
}
|
|
|
|
// DecodeContainerConfig decodes a json encoded config into a ContainerConfigWrapper
|
|
// struct and returns both a Config and a HostConfig struct
|
|
// Be aware this function is not checking whether the resulted structs are nil,
|
|
// it's your business to do so
|
|
func DecodeContainerConfig(src io.Reader) (*container.Config, *container.HostConfig, *networktypes.NetworkingConfig, error) {
|
|
var w ContainerConfigWrapper
|
|
|
|
decoder := json.NewDecoder(src)
|
|
if err := decoder.Decode(&w); err != nil {
|
|
return nil, nil, nil, err
|
|
}
|
|
|
|
hc := w.getHostConfig()
|
|
|
|
// Perform platform-specific processing of Volumes and Binds.
|
|
if w.Config != nil && hc != nil {
|
|
|
|
// Initialize the volumes map if currently nil
|
|
if w.Config.Volumes == nil {
|
|
w.Config.Volumes = make(map[string]struct{})
|
|
}
|
|
|
|
// Now validate all the volumes and binds
|
|
if err := validateVolumesAndBindSettings(w.Config, hc); err != nil {
|
|
return nil, nil, nil, err
|
|
}
|
|
}
|
|
|
|
// Certain parameters need daemon-side validation that cannot be done
|
|
// on the client, as only the daemon knows what is valid for the platform.
|
|
if err := ValidateNetMode(w.Config, hc); err != nil {
|
|
return nil, nil, nil, err
|
|
}
|
|
|
|
// Validate isolation
|
|
if err := ValidateIsolation(hc); err != nil {
|
|
return nil, nil, nil, err
|
|
}
|
|
|
|
// Validate QoS
|
|
if err := ValidateQoS(hc); err != nil {
|
|
return nil, nil, nil, err
|
|
}
|
|
|
|
// Validate Resources
|
|
if err := ValidateResources(hc, sysinfo.New(true)); err != nil {
|
|
return nil, nil, nil, err
|
|
}
|
|
return w.Config, hc, w.NetworkingConfig, nil
|
|
}
|
|
|
|
// validateVolumesAndBindSettings validates each of the volumes and bind settings
|
|
// passed by the caller to ensure they are valid.
|
|
func validateVolumesAndBindSettings(c *container.Config, hc *container.HostConfig) error {
|
|
if len(hc.Mounts) > 0 {
|
|
if len(hc.Binds) > 0 {
|
|
return conflictError(fmt.Errorf("must not specify both Binds and Mounts"))
|
|
}
|
|
|
|
if len(c.Volumes) > 0 {
|
|
return conflictError(fmt.Errorf("must not specify both Volumes and Mounts"))
|
|
}
|
|
|
|
if len(hc.VolumeDriver) > 0 {
|
|
return conflictError(fmt.Errorf("must not specify both VolumeDriver and Mounts"))
|
|
}
|
|
}
|
|
|
|
// Ensure all volumes and binds are valid.
|
|
for spec := range c.Volumes {
|
|
if _, err := volume.ParseMountRaw(spec, hc.VolumeDriver); err != nil {
|
|
return fmt.Errorf("invalid volume spec %q: %v", spec, err)
|
|
}
|
|
}
|
|
for _, spec := range hc.Binds {
|
|
if _, err := volume.ParseMountRaw(spec, hc.VolumeDriver); err != nil {
|
|
return fmt.Errorf("invalid bind mount spec %q: %v", spec, err)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|