From b50266335ef3ac500664bb2e651cf783adb271c0 Mon Sep 17 00:00:00 2001 From: Vishnu Kannan Date: Thu, 19 Jun 2014 23:36:39 +0000 Subject: [PATCH 01/12] Updated libcontainer subpackage dependencies. Most subpackages now do not depend on their parent ('libcontainer') package. 'namespaces' and 'nsinit' still do. 'namespaces' need to refactored a bit more to move the API part of it to 'libcontainer' package and keep the namespace specific code inside that package. This change is not expected to break docker. Docker-DCO-1.1-Signed-off-by: Vishnu Kannan (github: vishh) --- container.go | 77 ++++----- mount/init.go | 25 ++- mount/nodes/nodes_unsupported.go | 3 +- mount/types.go | 47 ++++++ namespaces/exec.go | 8 +- namespaces/init.go | 12 +- namespaces/sync_pipe.go | 8 +- namespaces/types.go | 50 ++++++ types_linux.go => namespaces/types_linux.go | 2 +- types_test.go => namespaces/types_test.go | 16 +- namespaces/unsupported.go | 9 +- network/loopback.go | 5 +- network/netns.go | 7 +- network/strategy.go | 6 +- network/types.go | 29 ++++ network/veth.go | 19 ++- security/capabilities/capabilities.go | 15 +- security/capabilities/types.go | 90 +++++++++++ security/capabilities/types_test.go | 19 +++ types.go | 165 -------------------- utils.go | 41 +++++ 21 files changed, 375 insertions(+), 278 deletions(-) create mode 100644 mount/types.go create mode 100644 namespaces/types.go rename types_linux.go => namespaces/types_linux.go (95%) rename types_test.go => namespaces/types_test.go (62%) create mode 100644 network/types.go create mode 100644 security/capabilities/types.go create mode 100644 security/capabilities/types_test.go delete mode 100644 types.go create mode 100644 utils.go diff --git a/container.go b/container.go index be72d92ee..feaa7661f 100644 --- a/container.go +++ b/container.go @@ -8,18 +8,54 @@ import ( // Context is a generic key value pair that allows arbatrary data to be sent type Context map[string]string +type Mount struct { + Type string `json:"type,omitempty"` + Source string `json:"source,omitempty"` // Source path, in the host namespace + Destination string `json:"destination,omitempty"` // Destination path, in the container + Writable bool `json:"writable,omitempty"` + Private bool `json:"private,omitempty"` +} + +type Mounts []Mount + +type Network struct { + // Type sets the networks type, commonly veth and loopback + Type string `json:"type,omitempty"` + + // Context is a generic key value format for setting additional options that are specific to + // the network type + Context Context `json:"context,omitempty"` + + // Address contains the IP and mask to set on the network interface + Address string `json:"address,omitempty"` + + // Gateway sets the gateway address that is used as the default for the interface + Gateway string `json:"gateway,omitempty"` + + // Mtu sets the mtu value for the interface and will be mirrored on both the host and + // container's interfaces if a pair is created, specifically in the case of type veth + Mtu int `json:"mtu,omitempty"` +} + // Container defines configuration options for executing a process inside a contained environment type Container struct { - // Hostname optionally sets the container's hostname if provided - Hostname string `json:"hostname,omitempty"` + // NoPivotRoot will use MS_MOVE and a chroot to jail the process into the container's rootfs + // This is a common option when the container is running in ramdisk + NoPivotRoot bool `json:"no_pivot_root,omitempty"` // ReadonlyFs will remount the container's rootfs as readonly where only externally mounted // bind mounts are writtable ReadonlyFs bool `json:"readonly_fs,omitempty"` - // NoPivotRoot will use MS_MOVE and a chroot to jail the process into the container's rootfs - // This is a common option when the container is running in ramdisk - NoPivotRoot bool `json:"no_pivot_root,omitempty"` + // Mounts specify additional source and destination paths that will be mounted inside the container's + // rootfs and mount namespace if specified + Mounts Mounts `json:"mounts,omitempty"` + + // The device nodes that should be automatically created within the container upon container start. Note, make sure that the node is marked as allowed in the cgroup as well! + DeviceNodes []*devices.Device `json:"device_nodes,omitempty"` + + // Hostname optionally sets the container's hostname if provided + Hostname string `json:"hostname,omitempty"` // User will set the uid and gid of the executing process running inside the container User string `json:"user,omitempty"` @@ -58,37 +94,8 @@ type Container struct { // on the container's creation // This is commonly used to specify apparmor profiles, selinux labels, and different restrictions // placed on the container's processes + // TODO(vishh): Strongtype this. Context Context `json:"context,omitempty"` - - // Mounts specify additional source and destination paths that will be mounted inside the container's - // rootfs and mount namespace if specified - Mounts Mounts `json:"mounts,omitempty"` - - // The device nodes that should be automatically created within the container upon container start. Note, make sure that the node is marked as allowed in the cgroup as well! - DeviceNodes []*devices.Device `json:"device_nodes,omitempty"` -} - -// Network defines configuration for a container's networking stack -// -// The network configuration can be omited from a container causing the -// container to be setup with the host's networking stack -type Network struct { - // Type sets the networks type, commonly veth and loopback - Type string `json:"type,omitempty"` - - // Context is a generic key value format for setting additional options that are specific to - // the network type - Context Context `json:"context,omitempty"` - - // Address contains the IP and mask to set on the network interface - Address string `json:"address,omitempty"` - - // Gateway sets the gateway address that is used as the default for the interface - Gateway string `json:"gateway,omitempty"` - - // Mtu sets the mtu value for the interface and will be mirrored on both the host and - // container's interfaces if a pair is created, specifically in the case of type veth - Mtu int `json:"mtu,omitempty"` } // Routes can be specified to create entries in the route table as the container is started diff --git a/mount/init.go b/mount/init.go index 4e913ad1e..bef83885a 100644 --- a/mount/init.go +++ b/mount/init.go @@ -8,7 +8,6 @@ import ( "path/filepath" "syscall" - "github.com/docker/libcontainer" "github.com/docker/libcontainer/label" "github.com/docker/libcontainer/mount/nodes" "github.com/dotcloud/docker/pkg/symlink" @@ -28,12 +27,12 @@ type mount struct { // InitializeMountNamespace setups up the devices, mount points, and filesystems for use inside a // new mount namepsace -func InitializeMountNamespace(rootfs, console string, container *libcontainer.Container) error { +func InitializeMountNamespace(rootfs, console string, MountSpec *MountSpec) error { var ( err error flag = syscall.MS_PRIVATE ) - if container.NoPivotRoot { + if MountSpec.NoPivotRoot { flag = syscall.MS_SLAVE } if err := system.Mount("", "/", "", uintptr(flag|syscall.MS_REC), ""); err != nil { @@ -42,16 +41,16 @@ func InitializeMountNamespace(rootfs, console string, container *libcontainer.Co if err := system.Mount(rootfs, rootfs, "bind", syscall.MS_BIND|syscall.MS_REC, ""); err != nil { return fmt.Errorf("mouting %s as bind %s", rootfs, err) } - if err := mountSystem(rootfs, container); err != nil { + if err := mountSystem(rootfs, MountSpec); err != nil { return fmt.Errorf("mount system %s", err) } - if err := setupBindmounts(rootfs, container.Mounts); err != nil { + if err := setupBindmounts(rootfs, MountSpec.Mounts); err != nil { return fmt.Errorf("bind mounts %s", err) } - if err := nodes.CreateDeviceNodes(rootfs, container.DeviceNodes); err != nil { + if err := nodes.CreateDeviceNodes(rootfs, MountSpec.DeviceNodes); err != nil { return fmt.Errorf("create device nodes %s", err) } - if err := SetupPtmx(rootfs, console, container.Context["mount_label"]); err != nil { + if err := SetupPtmx(rootfs, console, MountSpec.MountLabel); err != nil { return err } if err := setupDevSymlinks(rootfs); err != nil { @@ -61,7 +60,7 @@ func InitializeMountNamespace(rootfs, console string, container *libcontainer.Co return fmt.Errorf("chdir into %s %s", rootfs, err) } - if container.NoPivotRoot { + if MountSpec.NoPivotRoot { err = MsMoveRoot(rootfs) } else { err = PivotRoot(rootfs) @@ -70,7 +69,7 @@ func InitializeMountNamespace(rootfs, console string, container *libcontainer.Co return err } - if container.ReadonlyFs { + if MountSpec.ReadonlyFs { if err := SetReadonly(); err != nil { return fmt.Errorf("set readonly %s", err) } @@ -83,8 +82,8 @@ func InitializeMountNamespace(rootfs, console string, container *libcontainer.Co // mountSystem sets up linux specific system mounts like sys, proc, shm, and devpts // inside the mount namespace -func mountSystem(rootfs string, container *libcontainer.Container) error { - for _, m := range newSystemMounts(rootfs, container.Context["mount_label"], container.Mounts) { +func mountSystem(rootfs string, MountSpec *MountSpec) error { + for _, m := range newSystemMounts(rootfs, MountSpec.MountLabel, MountSpec.Mounts) { if err := os.MkdirAll(m.path, 0755); err != nil && !os.IsExist(err) { return fmt.Errorf("mkdirall %s %s", m.path, err) } @@ -145,7 +144,7 @@ func setupDevSymlinks(rootfs string) error { return nil } -func setupBindmounts(rootfs string, bindMounts libcontainer.Mounts) error { +func setupBindmounts(rootfs string, bindMounts Mounts) error { for _, m := range bindMounts.OfType("bind") { var ( flags = syscall.MS_BIND | syscall.MS_REC @@ -188,7 +187,7 @@ func setupBindmounts(rootfs string, bindMounts libcontainer.Mounts) error { // TODO: this is crappy right now and should be cleaned up with a better way of handling system and // standard bind mounts allowing them to be more dynamic -func newSystemMounts(rootfs, mountLabel string, mounts libcontainer.Mounts) []mount { +func newSystemMounts(rootfs, mountLabel string, mounts Mounts) []mount { systemMounts := []mount{ {source: "proc", path: filepath.Join(rootfs, "proc"), device: "proc", flags: defaultMountFlags}, {source: "sysfs", path: filepath.Join(rootfs, "sys"), device: "sysfs", flags: defaultMountFlags}, diff --git a/mount/nodes/nodes_unsupported.go b/mount/nodes/nodes_unsupported.go index 3811a1d73..00e59eb34 100644 --- a/mount/nodes/nodes_unsupported.go +++ b/mount/nodes/nodes_unsupported.go @@ -3,10 +3,9 @@ package nodes import ( - "github.com/docker/libcontainer" "github.com/docker/libcontainer/devices" ) func CreateDeviceNodes(rootfs string, nodesToCreate []*devices.Device) error { - return libcontainer.ErrUnsupported + return ErrUnsupported } diff --git a/mount/types.go b/mount/types.go new file mode 100644 index 000000000..3234c7539 --- /dev/null +++ b/mount/types.go @@ -0,0 +1,47 @@ +package mount + +import ( + "errors" + "github.com/docker/libcontainer/devices" +) + +type MountSpec struct { + // NoPivotRoot will use MS_MOVE and a chroot to jail the process into the container's rootfs + // This is a common option when the container is running in ramdisk + NoPivotRoot bool `json:"no_pivot_root,omitempty"` + + // ReadonlyFs will remount the container's rootfs as readonly where only externally mounted + // bind mounts are writtable + ReadonlyFs bool `json:"readonly_fs,omitempty"` + + // Mounts specify additional source and destination paths that will be mounted inside the container's + // rootfs and mount namespace if specified + Mounts Mounts `json:"mounts,omitempty"` + + // The device nodes that should be automatically created within the container upon container start. Note, make sure that the node is marked as allowed in the cgroup as well! + DeviceNodes []*devices.Device `json:"device_nodes,omitempty"` + + MountLabel string +} + +type Mount struct { + Type string `json:"type,omitempty"` + Source string `json:"source,omitempty"` // Source path, in the host namespace + Destination string `json:"destination,omitempty"` // Destination path, in the container + Writable bool `json:"writable,omitempty"` + Private bool `json:"private,omitempty"` +} + +type Mounts []Mount + +var ErrUnsupported = errors.New("Unsupported method") + +func (s Mounts) OfType(t string) Mounts { + out := Mounts{} + for _, m := range s { + if m.Type == t { + out = append(out, m) + } + } + return out +} diff --git a/namespaces/exec.go b/namespaces/exec.go index 31d5ba21d..0b5d4f5ec 100644 --- a/namespaces/exec.go +++ b/namespaces/exec.go @@ -15,6 +15,8 @@ import ( "github.com/dotcloud/docker/pkg/system" ) +// TODO(vishh): This is part of the libcontainer API and it does much more than just namespaces related work. +// Move this to libcontainer package. // Exec performes setup outside of a namespace so that a container can be // executed. Exec is a high level function for working with container namespaces. func Exec(container *libcontainer.Container, term Terminal, rootfs, dataPath string, args []string, createCommand CreateCommand, startCallback func()) (int, error) { @@ -149,13 +151,13 @@ func SetupCgroups(container *libcontainer.Container, nspid int) (cgroups.ActiveC // InitializeNetworking creates the container's network stack outside of the namespace and moves // interfaces into the container's net namespaces if necessary func InitializeNetworking(container *libcontainer.Container, nspid int, pipe *SyncPipe) error { - context := libcontainer.Context{} + context := map[string]string{} for _, config := range container.Networks { strategy, err := network.GetStrategy(config.Type) if err != nil { return err } - if err := strategy.Create(config, nspid, context); err != nil { + if err := strategy.Create(libcontainer.GetInternalNetworkSpec(config), nspid, context); err != nil { return err } } @@ -167,7 +169,7 @@ func InitializeNetworking(container *libcontainer.Container, nspid int, pipe *Sy func GetNamespaceFlags(namespaces map[string]bool) (flag int) { for key, enabled := range namespaces { if enabled { - if ns := libcontainer.GetNamespace(key); ns != nil { + if ns := GetNamespace(key); ns != nil { flag |= ns.Value } } diff --git a/namespaces/init.go b/namespaces/init.go index e89afdb47..61a545f5d 100644 --- a/namespaces/init.go +++ b/namespaces/init.go @@ -23,6 +23,8 @@ import ( "github.com/dotcloud/docker/pkg/user" ) +// TODO(vishh): This is part of the libcontainer API and it does much more than just namespaces related work. +// Move this to libcontainer package. // Init is the init process that first runs inside a new namespace to setup mounts, users, networking, // and other options required for the new container. func Init(container *libcontainer.Container, uncleanRootfs, consolePath string, syncPipe *SyncPipe, args []string) error { @@ -67,7 +69,7 @@ func Init(container *libcontainer.Container, uncleanRootfs, consolePath string, label.Init() - if err := mount.InitializeMountNamespace(rootfs, consolePath, container); err != nil { + if err := mount.InitializeMountNamespace(rootfs, consolePath, libcontainer.GetInternalMountSpec(container)); err != nil { return fmt.Errorf("setup mount namespace %s", err) } if container.Hostname != "" { @@ -157,14 +159,14 @@ func SetupUser(u string) error { // setupVethNetwork uses the Network config if it is not nil to initialize // the new veth interface inside the container for use by changing the name to eth0 // setting the MTU and IP address along with the default gateway -func setupNetwork(container *libcontainer.Container, context libcontainer.Context) error { +func setupNetwork(container *libcontainer.Container, context map[string]string) error { for _, config := range container.Networks { strategy, err := network.GetStrategy(config.Type) if err != nil { return err } - err1 := strategy.Initialize(config, context) + err1 := strategy.Initialize(libcontainer.GetInternalNetworkSpec(config), context) if err1 != nil { return err1 } @@ -193,7 +195,7 @@ func FinalizeNamespace(container *libcontainer.Container) error { } // drop capabilities in bounding set before changing user - if err := capabilities.DropBoundingSet(container); err != nil { + if err := capabilities.DropBoundingSet(&container.Capabilities); err != nil { return fmt.Errorf("drop bounding set %s", err) } @@ -211,7 +213,7 @@ func FinalizeNamespace(container *libcontainer.Container) error { } // drop all other capabilities - if err := capabilities.DropCapabilities(container); err != nil { + if err := capabilities.DropCapabilities(&container.Capabilities); err != nil { return fmt.Errorf("drop capabilities %s", err) } diff --git a/namespaces/sync_pipe.go b/namespaces/sync_pipe.go index 6fa846579..210ee5fbd 100644 --- a/namespaces/sync_pipe.go +++ b/namespaces/sync_pipe.go @@ -5,8 +5,6 @@ import ( "fmt" "io/ioutil" "os" - - "github.com/docker/libcontainer" ) // SyncPipe allows communication to and from the child processes @@ -45,7 +43,7 @@ func (s *SyncPipe) Parent() *os.File { return s.parent } -func (s *SyncPipe) SendToChild(context libcontainer.Context) error { +func (s *SyncPipe) SendToChild(context map[string]string) error { data, err := json.Marshal(context) if err != nil { return err @@ -54,12 +52,12 @@ func (s *SyncPipe) SendToChild(context libcontainer.Context) error { return nil } -func (s *SyncPipe) ReadFromParent() (libcontainer.Context, error) { +func (s *SyncPipe) ReadFromParent() (map[string]string, error) { data, err := ioutil.ReadAll(s.child) if err != nil { return nil, fmt.Errorf("error reading from sync pipe %s", err) } - var context libcontainer.Context + var context map[string]string if len(data) > 0 { if err := json.Unmarshal(data, &context); err != nil { return nil, err diff --git a/namespaces/types.go b/namespaces/types.go new file mode 100644 index 000000000..16ce981e8 --- /dev/null +++ b/namespaces/types.go @@ -0,0 +1,50 @@ +package namespaces + +import "errors" + +type ( + Namespace struct { + Key string `json:"key,omitempty"` + Value int `json:"value,omitempty"` + File string `json:"file,omitempty"` + } + Namespaces []*Namespace +) + +// namespaceList is used to convert the libcontainer types +// into the names of the files located in /proc//ns/* for +// each namespace +var ( + namespaceList = Namespaces{} + ErrUnkownNamespace = errors.New("Unknown namespace") + ErrUnsupported = errors.New("Unsupported method") +) + +func (ns *Namespace) String() string { + return ns.Key +} + +func GetNamespace(key string) *Namespace { + for _, ns := range namespaceList { + if ns.Key == key { + cpy := *ns + return &cpy + } + } + return nil +} + +// Contains returns true if the specified Namespace is +// in the slice +func (n Namespaces) Contains(ns string) bool { + return n.Get(ns) != nil +} + +func (n Namespaces) Get(ns string) *Namespace { + for _, nsp := range n { + if nsp != nil && nsp.Key == ns { + return nsp + } + } + return nil +} diff --git a/types_linux.go b/namespaces/types_linux.go similarity index 95% rename from types_linux.go rename to namespaces/types_linux.go index c14531df2..d3079944c 100644 --- a/types_linux.go +++ b/namespaces/types_linux.go @@ -1,4 +1,4 @@ -package libcontainer +package namespaces import ( "syscall" diff --git a/types_test.go b/namespaces/types_test.go similarity index 62% rename from types_test.go rename to namespaces/types_test.go index dd31298fd..4d0a72c9b 100644 --- a/types_test.go +++ b/namespaces/types_test.go @@ -1,4 +1,4 @@ -package libcontainer +package namespaces import ( "testing" @@ -28,17 +28,3 @@ func TestNamespacesContains(t *testing.T) { t.Fatal("namespaces should contain NEWPID but does not") } } - -func TestCapabilitiesContains(t *testing.T) { - caps := Capabilities{ - GetCapability("MKNOD"), - GetCapability("SETPCAP"), - } - - if caps.Contains("SYS_ADMIN") { - t.Fatal("capabilities should not contain SYS_ADMIN") - } - if !caps.Contains("MKNOD") { - t.Fatal("capabilities should contain MKNOD but does not") - } -} diff --git a/namespaces/unsupported.go b/namespaces/unsupported.go index a0653ee8a..5fa8832a3 100644 --- a/namespaces/unsupported.go +++ b/namespaces/unsupported.go @@ -3,24 +3,23 @@ package namespaces import ( - "github.com/docker/libcontainer" "github.com/docker/libcontainer/cgroups" ) func Exec(container *libcontainer.Container, term Terminal, rootfs, dataPath string, args []string, createCommand CreateCommand, startCallback func()) (int, error) { - return -1, libcontainer.ErrUnsupported + return -1, ErrUnsupported } func Init(container *libcontainer.Container, uncleanRootfs, consolePath string, syncPipe *SyncPipe, args []string) error { - return libcontainer.ErrUnsupported + return ErrUnsupported } func InitializeNetworking(container *libcontainer.Container, nspid int, pipe *SyncPipe) error { - return libcontainer.ErrUnsupported + return ErrUnsupported } func SetupCgroups(container *libcontainer.Container, nspid int) (cgroups.ActiveCgroup, error) { - return nil, libcontainer.ErrUnsupported + return nil, ErrUnsupported } func GetNamespaceFlags(namespaces map[string]bool) (flag int) { diff --git a/network/loopback.go b/network/loopback.go index 218d1959b..284a4e65f 100644 --- a/network/loopback.go +++ b/network/loopback.go @@ -2,18 +2,17 @@ package network import ( "fmt" - "github.com/docker/libcontainer" ) // Loopback is a network strategy that provides a basic loopback device type Loopback struct { } -func (l *Loopback) Create(n *libcontainer.Network, nspid int, context libcontainer.Context) error { +func (l *Loopback) Create(n *Network, nspid int, context map[string]string) error { return nil } -func (l *Loopback) Initialize(config *libcontainer.Network, context libcontainer.Context) error { +func (l *Loopback) Initialize(config *Network, context map[string]string) error { if err := SetMtu("lo", config.Mtu); err != nil { return fmt.Errorf("set lo mtu to %d %s", config.Mtu, err) } diff --git a/network/netns.go b/network/netns.go index e8a9188dd..4d132e7c7 100644 --- a/network/netns.go +++ b/network/netns.go @@ -5,7 +5,6 @@ import ( "os" "syscall" - "github.com/docker/libcontainer" "github.com/dotcloud/docker/pkg/system" ) @@ -13,12 +12,12 @@ import ( type NetNS struct { } -func (v *NetNS) Create(n *libcontainer.Network, nspid int, context libcontainer.Context) error { - context["nspath"] = n.Context["nspath"] +func (v *NetNS) Create(n *Network, nspid int, context map[string]string) error { + context["nspath"] = n.NsPath return nil } -func (v *NetNS) Initialize(config *libcontainer.Network, context libcontainer.Context) error { +func (v *NetNS) Initialize(config *Network, context map[string]string) error { nspath, exists := context["nspath"] if !exists { return fmt.Errorf("nspath does not exist in network context") diff --git a/network/strategy.go b/network/strategy.go index 321cf58e3..00813f6b7 100644 --- a/network/strategy.go +++ b/network/strategy.go @@ -2,8 +2,6 @@ package network import ( "errors" - - "github.com/docker/libcontainer" ) var ( @@ -19,8 +17,8 @@ var strategies = map[string]NetworkStrategy{ // NetworkStrategy represents a specific network configuration for // a container's networking stack type NetworkStrategy interface { - Create(*libcontainer.Network, int, libcontainer.Context) error - Initialize(*libcontainer.Network, libcontainer.Context) error + Create(*Network, int, map[string]string) error + Initialize(*Network, map[string]string) error } // GetStrategy returns the specific network strategy for the diff --git a/network/types.go b/network/types.go new file mode 100644 index 000000000..6a7fe3ee1 --- /dev/null +++ b/network/types.go @@ -0,0 +1,29 @@ +package network + +// Network defines configuration for a container's networking stack +// +// The network configuration can be omited from a container causing the +// container to be setup with the host's networking stack +type Network struct { + // Type sets the networks type, commonly veth and loopback + Type string `json:"type,omitempty"` + + // Path to network namespace + NsPath string + + // The bridge to use. + Bridge string + + // Prefix for the veth interfaces. + VethPrefix string + + // Address contains the IP and mask to set on the network interface + Address string `json:"address,omitempty"` + + // Gateway sets the gateway address that is used as the default for the interface + Gateway string `json:"gateway,omitempty"` + + // Mtu sets the mtu value for the interface and will be mirrored on both the host and + // container's interfaces if a pair is created, specifically in the case of type veth + Mtu int `json:"mtu,omitempty"` +} diff --git a/network/veth.go b/network/veth.go index 4dad4aa20..817144fa2 100644 --- a/network/veth.go +++ b/network/veth.go @@ -2,7 +2,7 @@ package network import ( "fmt" - "github.com/docker/libcontainer" + "github.com/docker/libcontainer/utils" ) @@ -14,17 +14,16 @@ type Veth struct { const defaultDevice = "eth0" -func (v *Veth) Create(n *libcontainer.Network, nspid int, context libcontainer.Context) error { +func (v *Veth) Create(n *Network, nspid int, context map[string]string) error { var ( - bridge string - prefix string - exists bool + bridge = n.Bridge + prefix = n.VethPrefix ) - if bridge, exists = n.Context["bridge"]; !exists { - return fmt.Errorf("bridge does not exist in network context") + if bridge == "" { + return fmt.Errorf("bridge is not specified") } - if prefix, exists = n.Context["prefix"]; !exists { - return fmt.Errorf("veth prefix does not exist in network context") + if prefix == "" { + return fmt.Errorf("veth prefix is not specified") } name1, name2, err := createVethPair(prefix) if err != nil { @@ -47,7 +46,7 @@ func (v *Veth) Create(n *libcontainer.Network, nspid int, context libcontainer.C return nil } -func (v *Veth) Initialize(config *libcontainer.Network, context libcontainer.Context) error { +func (v *Veth) Initialize(config *Network, context map[string]string) error { var ( vethChild string exists bool diff --git a/security/capabilities/capabilities.go b/security/capabilities/capabilities.go index ef872178f..e1f022d3f 100644 --- a/security/capabilities/capabilities.go +++ b/security/capabilities/capabilities.go @@ -3,7 +3,6 @@ package capabilities import ( "os" - "github.com/docker/libcontainer" "github.com/syndtr/gocapability/capability" ) @@ -11,13 +10,13 @@ const allCapabilityTypes = capability.CAPS | capability.BOUNDS // DropBoundingSet drops the capability bounding set to those specified in the // container configuration. -func DropBoundingSet(container *libcontainer.Container) error { +func DropBoundingSet(capabilities *[]string) error { c, err := capability.NewPid(os.Getpid()) if err != nil { return err } - keep := getEnabledCapabilities(container) + keep := getEnabledCapabilities(capabilities) c.Clear(capability.BOUNDS) c.Set(capability.BOUNDS, keep...) @@ -29,13 +28,13 @@ func DropBoundingSet(container *libcontainer.Container) error { } // DropCapabilities drops all capabilities for the current process expect those specified in the container configuration. -func DropCapabilities(container *libcontainer.Container) error { +func DropCapabilities(capList *[]string) error { c, err := capability.NewPid(os.Getpid()) if err != nil { return err } - keep := getEnabledCapabilities(container) + keep := getEnabledCapabilities(capList) c.Clear(allCapabilityTypes) c.Set(allCapabilityTypes, keep...) @@ -46,10 +45,10 @@ func DropCapabilities(container *libcontainer.Container) error { } // getEnabledCapabilities returns the capabilities that should not be dropped by the container. -func getEnabledCapabilities(container *libcontainer.Container) []capability.Cap { +func getEnabledCapabilities(capList *[]string) []capability.Cap { keep := []capability.Cap{} - for _, capability := range container.Capabilities { - if c := libcontainer.GetCapability(capability); c != nil { + for _, capability := range *capList { + if c := GetCapability(capability); c != nil { keep = append(keep, c.Value) } } diff --git a/security/capabilities/types.go b/security/capabilities/types.go new file mode 100644 index 000000000..feb38e333 --- /dev/null +++ b/security/capabilities/types.go @@ -0,0 +1,90 @@ +package capabilities + +import "github.com/syndtr/gocapability/capability" + +type ( + CapabilityMapping struct { + Key string `json:"key,omitempty"` + Value capability.Cap `json:"value,omitempty"` + } + Capabilities []*CapabilityMapping +) + +func (c *CapabilityMapping) String() string { + return c.Key +} + +func GetCapability(key string) *CapabilityMapping { + for _, capp := range capabilityList { + if capp.Key == key { + cpy := *capp + return &cpy + } + } + return nil +} + +func GetAllCapabilities() []string { + output := make([]string, len(capabilityList)) + for i, capability := range capabilityList { + output[i] = capability.String() + } + return output +} + +// Contains returns true if the specified Capability is +// in the slice +func (c Capabilities) contains(capp string) bool { + return c.get(capp) != nil +} + +func (c Capabilities) get(capp string) *CapabilityMapping { + for _, cap := range c { + if cap.Key == capp { + return cap + } + } + return nil +} + +var capabilityList = Capabilities{ + {Key: "SETPCAP", Value: capability.CAP_SETPCAP}, + {Key: "SYS_MODULE", Value: capability.CAP_SYS_MODULE}, + {Key: "SYS_RAWIO", Value: capability.CAP_SYS_RAWIO}, + {Key: "SYS_PACCT", Value: capability.CAP_SYS_PACCT}, + {Key: "SYS_ADMIN", Value: capability.CAP_SYS_ADMIN}, + {Key: "SYS_NICE", Value: capability.CAP_SYS_NICE}, + {Key: "SYS_RESOURCE", Value: capability.CAP_SYS_RESOURCE}, + {Key: "SYS_TIME", Value: capability.CAP_SYS_TIME}, + {Key: "SYS_TTY_CONFIG", Value: capability.CAP_SYS_TTY_CONFIG}, + {Key: "MKNOD", Value: capability.CAP_MKNOD}, + {Key: "AUDIT_WRITE", Value: capability.CAP_AUDIT_WRITE}, + {Key: "AUDIT_CONTROL", Value: capability.CAP_AUDIT_CONTROL}, + {Key: "MAC_OVERRIDE", Value: capability.CAP_MAC_OVERRIDE}, + {Key: "MAC_ADMIN", Value: capability.CAP_MAC_ADMIN}, + {Key: "NET_ADMIN", Value: capability.CAP_NET_ADMIN}, + {Key: "SYSLOG", Value: capability.CAP_SYSLOG}, + {Key: "SETUID", Value: capability.CAP_SETUID}, + {Key: "SETGID", Value: capability.CAP_SETGID}, + {Key: "CHOWN", Value: capability.CAP_CHOWN}, + {Key: "NET_RAW", Value: capability.CAP_NET_RAW}, + {Key: "DAC_OVERRIDE", Value: capability.CAP_DAC_OVERRIDE}, + {Key: "FOWNER", Value: capability.CAP_FOWNER}, + {Key: "DAC_READ_SEARCH", Value: capability.CAP_DAC_READ_SEARCH}, + {Key: "FSETID", Value: capability.CAP_FSETID}, + {Key: "KILL", Value: capability.CAP_KILL}, + {Key: "SETGID", Value: capability.CAP_SETGID}, + {Key: "SETUID", Value: capability.CAP_SETUID}, + {Key: "LINUX_IMMUTABLE", Value: capability.CAP_LINUX_IMMUTABLE}, + {Key: "NET_BIND_SERVICE", Value: capability.CAP_NET_BIND_SERVICE}, + {Key: "NET_BROADCAST", Value: capability.CAP_NET_BROADCAST}, + {Key: "IPC_LOCK", Value: capability.CAP_IPC_LOCK}, + {Key: "IPC_OWNER", Value: capability.CAP_IPC_OWNER}, + {Key: "SYS_CHROOT", Value: capability.CAP_SYS_CHROOT}, + {Key: "SYS_PTRACE", Value: capability.CAP_SYS_PTRACE}, + {Key: "SYS_BOOT", Value: capability.CAP_SYS_BOOT}, + {Key: "LEASE", Value: capability.CAP_LEASE}, + {Key: "SETFCAP", Value: capability.CAP_SETFCAP}, + {Key: "WAKE_ALARM", Value: capability.CAP_WAKE_ALARM}, + {Key: "BLOCK_SUSPEND", Value: capability.CAP_BLOCK_SUSPEND}, +} diff --git a/security/capabilities/types_test.go b/security/capabilities/types_test.go new file mode 100644 index 000000000..34b026265 --- /dev/null +++ b/security/capabilities/types_test.go @@ -0,0 +1,19 @@ +package capabilities + +import ( + "testing" +) + +func TestCapabilitiesContains(t *testing.T) { + caps := Capabilities{ + GetCapability("MKNOD"), + GetCapability("SETPCAP"), + } + + if caps.Contains("SYS_ADMIN") { + t.Fatal("capabilities should not contain SYS_ADMIN") + } + if !caps.Contains("MKNOD") { + t.Fatal("capabilities should contain MKNOD but does not") + } +} diff --git a/types.go b/types.go deleted file mode 100644 index 834201036..000000000 --- a/types.go +++ /dev/null @@ -1,165 +0,0 @@ -package libcontainer - -import ( - "errors" - - "github.com/syndtr/gocapability/capability" -) - -var ( - ErrUnkownNamespace = errors.New("Unknown namespace") - ErrUnkownCapability = errors.New("Unknown capability") - ErrUnsupported = errors.New("Unsupported method") -) - -type Mounts []Mount - -func (s Mounts) OfType(t string) Mounts { - out := Mounts{} - for _, m := range s { - if m.Type == t { - out = append(out, m) - } - } - return out -} - -type Mount struct { - Type string `json:"type,omitempty"` - Source string `json:"source,omitempty"` // Source path, in the host namespace - Destination string `json:"destination,omitempty"` // Destination path, in the container - Writable bool `json:"writable,omitempty"` - Private bool `json:"private,omitempty"` -} - -// namespaceList is used to convert the libcontainer types -// into the names of the files located in /proc//ns/* for -// each namespace -var ( - namespaceList = Namespaces{} - - capabilityList = Capabilities{ - {Key: "SETPCAP", Value: capability.CAP_SETPCAP}, - {Key: "SYS_MODULE", Value: capability.CAP_SYS_MODULE}, - {Key: "SYS_RAWIO", Value: capability.CAP_SYS_RAWIO}, - {Key: "SYS_PACCT", Value: capability.CAP_SYS_PACCT}, - {Key: "SYS_ADMIN", Value: capability.CAP_SYS_ADMIN}, - {Key: "SYS_NICE", Value: capability.CAP_SYS_NICE}, - {Key: "SYS_RESOURCE", Value: capability.CAP_SYS_RESOURCE}, - {Key: "SYS_TIME", Value: capability.CAP_SYS_TIME}, - {Key: "SYS_TTY_CONFIG", Value: capability.CAP_SYS_TTY_CONFIG}, - {Key: "MKNOD", Value: capability.CAP_MKNOD}, - {Key: "AUDIT_WRITE", Value: capability.CAP_AUDIT_WRITE}, - {Key: "AUDIT_CONTROL", Value: capability.CAP_AUDIT_CONTROL}, - {Key: "MAC_OVERRIDE", Value: capability.CAP_MAC_OVERRIDE}, - {Key: "MAC_ADMIN", Value: capability.CAP_MAC_ADMIN}, - {Key: "NET_ADMIN", Value: capability.CAP_NET_ADMIN}, - {Key: "SYSLOG", Value: capability.CAP_SYSLOG}, - {Key: "SETUID", Value: capability.CAP_SETUID}, - {Key: "SETGID", Value: capability.CAP_SETGID}, - {Key: "CHOWN", Value: capability.CAP_CHOWN}, - {Key: "NET_RAW", Value: capability.CAP_NET_RAW}, - {Key: "DAC_OVERRIDE", Value: capability.CAP_DAC_OVERRIDE}, - {Key: "FOWNER", Value: capability.CAP_FOWNER}, - {Key: "DAC_READ_SEARCH", Value: capability.CAP_DAC_READ_SEARCH}, - {Key: "FSETID", Value: capability.CAP_FSETID}, - {Key: "KILL", Value: capability.CAP_KILL}, - {Key: "SETGID", Value: capability.CAP_SETGID}, - {Key: "SETUID", Value: capability.CAP_SETUID}, - {Key: "LINUX_IMMUTABLE", Value: capability.CAP_LINUX_IMMUTABLE}, - {Key: "NET_BIND_SERVICE", Value: capability.CAP_NET_BIND_SERVICE}, - {Key: "NET_BROADCAST", Value: capability.CAP_NET_BROADCAST}, - {Key: "IPC_LOCK", Value: capability.CAP_IPC_LOCK}, - {Key: "IPC_OWNER", Value: capability.CAP_IPC_OWNER}, - {Key: "SYS_CHROOT", Value: capability.CAP_SYS_CHROOT}, - {Key: "SYS_PTRACE", Value: capability.CAP_SYS_PTRACE}, - {Key: "SYS_BOOT", Value: capability.CAP_SYS_BOOT}, - {Key: "LEASE", Value: capability.CAP_LEASE}, - {Key: "SETFCAP", Value: capability.CAP_SETFCAP}, - {Key: "WAKE_ALARM", Value: capability.CAP_WAKE_ALARM}, - {Key: "BLOCK_SUSPEND", Value: capability.CAP_BLOCK_SUSPEND}, - } -) - -type ( - Namespace struct { - Key string `json:"key,omitempty"` - Value int `json:"value,omitempty"` - File string `json:"file,omitempty"` - } - Namespaces []*Namespace -) - -func (ns *Namespace) String() string { - return ns.Key -} - -func GetNamespace(key string) *Namespace { - for _, ns := range namespaceList { - if ns.Key == key { - cpy := *ns - return &cpy - } - } - return nil -} - -// Contains returns true if the specified Namespace is -// in the slice -func (n Namespaces) Contains(ns string) bool { - return n.Get(ns) != nil -} - -func (n Namespaces) Get(ns string) *Namespace { - for _, nsp := range n { - if nsp != nil && nsp.Key == ns { - return nsp - } - } - return nil -} - -type ( - Capability struct { - Key string `json:"key,omitempty"` - Value capability.Cap `json:"value,omitempty"` - } - Capabilities []*Capability -) - -func (c *Capability) String() string { - return c.Key -} - -func GetCapability(key string) *Capability { - for _, capp := range capabilityList { - if capp.Key == key { - cpy := *capp - return &cpy - } - } - return nil -} - -func GetAllCapabilities() []string { - output := make([]string, len(capabilityList)) - for i, capability := range capabilityList { - output[i] = capability.String() - } - return output -} - -// Contains returns true if the specified Capability is -// in the slice -func (c Capabilities) Contains(capp string) bool { - return c.Get(capp) != nil -} - -func (c Capabilities) Get(capp string) *Capability { - for _, cap := range c { - if cap.Key == capp { - return cap - } - } - return nil -} diff --git a/utils.go b/utils.go new file mode 100644 index 000000000..cc7b6b5d8 --- /dev/null +++ b/utils.go @@ -0,0 +1,41 @@ +package libcontainer + +import ( + "github.com/docker/libcontainer/mount" + "github.com/docker/libcontainer/network" + "github.com/docker/libcontainer/security/capabilities" +) + +func GetInternalMountSpec(container *Container) *mount.MountSpec { + out := &mount.MountSpec{ + NoPivotRoot: container.NoPivotRoot, + ReadonlyFs: container.ReadonlyFs, + DeviceNodes: container.DeviceNodes, + MountLabel: container.Context["mount_label"], + } + for _, mountFromSpec := range container.Mounts { + out.Mounts = append(out.Mounts, mount.Mount{ + Type: mountFromSpec.Type, + Source: mountFromSpec.Source, + Destination: mountFromSpec.Destination, + Writable: mountFromSpec.Writable, + Private: mountFromSpec.Private}) + } + return out +} + +func GetInternalNetworkSpec(net *Network) *network.Network { + return &network.Network{ + Type: net.Type, + NsPath: net.Context["nspath"], + Bridge: net.Context["bridge"], + VethPrefix: net.Context["prefix"], + Address: net.Address, + Gateway: net.Gateway, + Mtu: net.Mtu, + } +} + +func GetAllCapabilities() []string { + return capabilities.GetAllCapabilities() +} From 4c55db7d58804f52e8e26b0c92a762cb9ce933ce Mon Sep 17 00:00:00 2001 From: Vishnu Kannan Date: Mon, 23 Jun 2014 18:09:36 +0000 Subject: [PATCH 02/12] Rename MountSpec to MountConfig. Docker-DCO-1.1-Signed-off-by: Vishnu Kannan (github: vishh) --- mount/init.go | 20 ++++++++++---------- mount/types.go | 2 +- namespaces/init.go | 2 +- utils.go | 4 ++-- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/mount/init.go b/mount/init.go index bef83885a..53e880517 100644 --- a/mount/init.go +++ b/mount/init.go @@ -27,12 +27,12 @@ type mount struct { // InitializeMountNamespace setups up the devices, mount points, and filesystems for use inside a // new mount namepsace -func InitializeMountNamespace(rootfs, console string, MountSpec *MountSpec) error { +func InitializeMountNamespace(rootfs, console string, MountConfig *MountConfig) error { var ( err error flag = syscall.MS_PRIVATE ) - if MountSpec.NoPivotRoot { + if MountConfig.NoPivotRoot { flag = syscall.MS_SLAVE } if err := system.Mount("", "/", "", uintptr(flag|syscall.MS_REC), ""); err != nil { @@ -41,16 +41,16 @@ func InitializeMountNamespace(rootfs, console string, MountSpec *MountSpec) erro if err := system.Mount(rootfs, rootfs, "bind", syscall.MS_BIND|syscall.MS_REC, ""); err != nil { return fmt.Errorf("mouting %s as bind %s", rootfs, err) } - if err := mountSystem(rootfs, MountSpec); err != nil { + if err := mountSystem(rootfs, MountConfig); err != nil { return fmt.Errorf("mount system %s", err) } - if err := setupBindmounts(rootfs, MountSpec.Mounts); err != nil { + if err := setupBindmounts(rootfs, MountConfig.Mounts); err != nil { return fmt.Errorf("bind mounts %s", err) } - if err := nodes.CreateDeviceNodes(rootfs, MountSpec.DeviceNodes); err != nil { + if err := nodes.CreateDeviceNodes(rootfs, MountConfig.DeviceNodes); err != nil { return fmt.Errorf("create device nodes %s", err) } - if err := SetupPtmx(rootfs, console, MountSpec.MountLabel); err != nil { + if err := SetupPtmx(rootfs, console, MountConfig.MountLabel); err != nil { return err } if err := setupDevSymlinks(rootfs); err != nil { @@ -60,7 +60,7 @@ func InitializeMountNamespace(rootfs, console string, MountSpec *MountSpec) erro return fmt.Errorf("chdir into %s %s", rootfs, err) } - if MountSpec.NoPivotRoot { + if MountConfig.NoPivotRoot { err = MsMoveRoot(rootfs) } else { err = PivotRoot(rootfs) @@ -69,7 +69,7 @@ func InitializeMountNamespace(rootfs, console string, MountSpec *MountSpec) erro return err } - if MountSpec.ReadonlyFs { + if MountConfig.ReadonlyFs { if err := SetReadonly(); err != nil { return fmt.Errorf("set readonly %s", err) } @@ -82,8 +82,8 @@ func InitializeMountNamespace(rootfs, console string, MountSpec *MountSpec) erro // mountSystem sets up linux specific system mounts like sys, proc, shm, and devpts // inside the mount namespace -func mountSystem(rootfs string, MountSpec *MountSpec) error { - for _, m := range newSystemMounts(rootfs, MountSpec.MountLabel, MountSpec.Mounts) { +func mountSystem(rootfs string, MountConfig *MountConfig) error { + for _, m := range newSystemMounts(rootfs, MountConfig.MountLabel, MountConfig.Mounts) { if err := os.MkdirAll(m.path, 0755); err != nil && !os.IsExist(err) { return fmt.Errorf("mkdirall %s %s", m.path, err) } diff --git a/mount/types.go b/mount/types.go index 3234c7539..54586e7ef 100644 --- a/mount/types.go +++ b/mount/types.go @@ -5,7 +5,7 @@ import ( "github.com/docker/libcontainer/devices" ) -type MountSpec struct { +type MountConfig struct { // NoPivotRoot will use MS_MOVE and a chroot to jail the process into the container's rootfs // This is a common option when the container is running in ramdisk NoPivotRoot bool `json:"no_pivot_root,omitempty"` diff --git a/namespaces/init.go b/namespaces/init.go index 61a545f5d..5b97b1cb8 100644 --- a/namespaces/init.go +++ b/namespaces/init.go @@ -69,7 +69,7 @@ func Init(container *libcontainer.Container, uncleanRootfs, consolePath string, label.Init() - if err := mount.InitializeMountNamespace(rootfs, consolePath, libcontainer.GetInternalMountSpec(container)); err != nil { + if err := mount.InitializeMountNamespace(rootfs, consolePath, libcontainer.GetInternalMountConfig(container)); err != nil { return fmt.Errorf("setup mount namespace %s", err) } if container.Hostname != "" { diff --git a/utils.go b/utils.go index cc7b6b5d8..d9c65c581 100644 --- a/utils.go +++ b/utils.go @@ -6,8 +6,8 @@ import ( "github.com/docker/libcontainer/security/capabilities" ) -func GetInternalMountSpec(container *Container) *mount.MountSpec { - out := &mount.MountSpec{ +func GetInternalMountConfig(container *Container) *mount.MountConfig { + out := &mount.MountConfig{ NoPivotRoot: container.NoPivotRoot, ReadonlyFs: container.ReadonlyFs, DeviceNodes: container.DeviceNodes, From ece2d83558ecdcf906fa1f22b2b89dbc0691914a Mon Sep 17 00:00:00 2001 From: Vishnu Kannan Date: Mon, 23 Jun 2014 18:30:25 +0000 Subject: [PATCH 03/12] Added DropCapabilities() and DropBoundingSet() API to libcontainer. Docker-DCO-1.1-Signed-off-by: Vishnu Kannan (github: vishh) --- namespaces/init.go | 4 ++-- security/capabilities/capabilities.go | 8 ++++---- security/capabilities/types_test.go | 4 ++-- utils.go | 8 ++++++++ 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/namespaces/init.go b/namespaces/init.go index 5b97b1cb8..8ea4ef697 100644 --- a/namespaces/init.go +++ b/namespaces/init.go @@ -195,7 +195,7 @@ func FinalizeNamespace(container *libcontainer.Container) error { } // drop capabilities in bounding set before changing user - if err := capabilities.DropBoundingSet(&container.Capabilities); err != nil { + if err := capabilities.DropBoundingSet(container.Capabilities); err != nil { return fmt.Errorf("drop bounding set %s", err) } @@ -213,7 +213,7 @@ func FinalizeNamespace(container *libcontainer.Container) error { } // drop all other capabilities - if err := capabilities.DropCapabilities(&container.Capabilities); err != nil { + if err := capabilities.DropCapabilities(container.Capabilities); err != nil { return fmt.Errorf("drop capabilities %s", err) } diff --git a/security/capabilities/capabilities.go b/security/capabilities/capabilities.go index e1f022d3f..21e4de26e 100644 --- a/security/capabilities/capabilities.go +++ b/security/capabilities/capabilities.go @@ -10,7 +10,7 @@ const allCapabilityTypes = capability.CAPS | capability.BOUNDS // DropBoundingSet drops the capability bounding set to those specified in the // container configuration. -func DropBoundingSet(capabilities *[]string) error { +func DropBoundingSet(capabilities []string) error { c, err := capability.NewPid(os.Getpid()) if err != nil { return err @@ -28,7 +28,7 @@ func DropBoundingSet(capabilities *[]string) error { } // DropCapabilities drops all capabilities for the current process expect those specified in the container configuration. -func DropCapabilities(capList *[]string) error { +func DropCapabilities(capList []string) error { c, err := capability.NewPid(os.Getpid()) if err != nil { return err @@ -45,9 +45,9 @@ func DropCapabilities(capList *[]string) error { } // getEnabledCapabilities returns the capabilities that should not be dropped by the container. -func getEnabledCapabilities(capList *[]string) []capability.Cap { +func getEnabledCapabilities(capList []string) []capability.Cap { keep := []capability.Cap{} - for _, capability := range *capList { + for _, capability := range capList { if c := GetCapability(capability); c != nil { keep = append(keep, c.Value) } diff --git a/security/capabilities/types_test.go b/security/capabilities/types_test.go index 34b026265..06e8a2b01 100644 --- a/security/capabilities/types_test.go +++ b/security/capabilities/types_test.go @@ -10,10 +10,10 @@ func TestCapabilitiesContains(t *testing.T) { GetCapability("SETPCAP"), } - if caps.Contains("SYS_ADMIN") { + if caps.contains("SYS_ADMIN") { t.Fatal("capabilities should not contain SYS_ADMIN") } - if !caps.Contains("MKNOD") { + if !caps.contains("MKNOD") { t.Fatal("capabilities should contain MKNOD but does not") } } diff --git a/utils.go b/utils.go index d9c65c581..a4e2e8844 100644 --- a/utils.go +++ b/utils.go @@ -39,3 +39,11 @@ func GetInternalNetworkSpec(net *Network) *network.Network { func GetAllCapabilities() []string { return capabilities.GetAllCapabilities() } + +func DropBoundingSet(container *Container) error { + return capabilities.DropBoundingSet(container.Capabilities) +} + +func DropCapabilities(container *Container) error { + return capabilities.DropCapabilities(container.Capabilities) +} From c5f93a9a480b262c60bca434b0941aeb7e5ba9ac Mon Sep 17 00:00:00 2001 From: Vishnu Kannan Date: Mon, 23 Jun 2014 18:41:39 +0000 Subject: [PATCH 04/12] Reuse internal mount.Mount in the API. Docker-DCO-1.1-Signed-off-by: Vishnu Kannan (github: vishh) --- container.go | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/container.go b/container.go index feaa7661f..1efb0db41 100644 --- a/container.go +++ b/container.go @@ -3,18 +3,14 @@ package libcontainer import ( "github.com/docker/libcontainer/cgroups" "github.com/docker/libcontainer/devices" + "github.com/docker/libcontainer/mount" ) // Context is a generic key value pair that allows arbatrary data to be sent type Context map[string]string -type Mount struct { - Type string `json:"type,omitempty"` - Source string `json:"source,omitempty"` // Source path, in the host namespace - Destination string `json:"destination,omitempty"` // Destination path, in the container - Writable bool `json:"writable,omitempty"` - Private bool `json:"private,omitempty"` -} +// Reusing internal Mount struct since we don't expect the API and the internal representation to differ much in the future. +type Mount mount.Mount type Mounts []Mount From 0f14662b9ce7210b5b51c3110a86b45e10abdc2e Mon Sep 17 00:00:00 2001 From: Vishnu Kannan Date: Mon, 23 Jun 2014 18:54:26 +0000 Subject: [PATCH 05/12] Remove 'Context' type from the libcontainer API. It will be a generic map with string key and value henceforth. Docker-DCO-1.1-Signed-off-by: Vishnu Kannan (github: vishh) --- container.go | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/container.go b/container.go index 1efb0db41..05d0a84b2 100644 --- a/container.go +++ b/container.go @@ -6,9 +6,6 @@ import ( "github.com/docker/libcontainer/mount" ) -// Context is a generic key value pair that allows arbatrary data to be sent -type Context map[string]string - // Reusing internal Mount struct since we don't expect the API and the internal representation to differ much in the future. type Mount mount.Mount @@ -20,7 +17,7 @@ type Network struct { // Context is a generic key value format for setting additional options that are specific to // the network type - Context Context `json:"context,omitempty"` + Context map[string]string `json:"context,omitempty"` // Address contains the IP and mask to set on the network interface Address string `json:"address,omitempty"` @@ -90,8 +87,8 @@ type Container struct { // on the container's creation // This is commonly used to specify apparmor profiles, selinux labels, and different restrictions // placed on the container's processes - // TODO(vishh): Strongtype this. - Context Context `json:"context,omitempty"` + // TODO(vishh): Avoid overloading this field with params for different subsystems. Strongtype this. + Context map[string]string `json:"context,omitempty"` } // Routes can be specified to create entries in the route table as the container is started From 561534244aa6f195a6dc3c5c786f0641b0806ed2 Mon Sep 17 00:00:00 2001 From: Vishnu Kannan Date: Mon, 23 Jun 2014 19:30:59 +0000 Subject: [PATCH 06/12] Minor fixes. Docker-DCO-1.1-Signed-off-by: Vishnu Kannan (github: vishh) --- mount/init.go | 20 ++++++++++---------- mount/types.go | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/mount/init.go b/mount/init.go index 53e880517..bc839e325 100644 --- a/mount/init.go +++ b/mount/init.go @@ -27,12 +27,12 @@ type mount struct { // InitializeMountNamespace setups up the devices, mount points, and filesystems for use inside a // new mount namepsace -func InitializeMountNamespace(rootfs, console string, MountConfig *MountConfig) error { +func InitializeMountNamespace(rootfs, console string, mountConfig *MountConfig) error { var ( err error flag = syscall.MS_PRIVATE ) - if MountConfig.NoPivotRoot { + if mountConfig.NoPivotRoot { flag = syscall.MS_SLAVE } if err := system.Mount("", "/", "", uintptr(flag|syscall.MS_REC), ""); err != nil { @@ -41,16 +41,16 @@ func InitializeMountNamespace(rootfs, console string, MountConfig *MountConfig) if err := system.Mount(rootfs, rootfs, "bind", syscall.MS_BIND|syscall.MS_REC, ""); err != nil { return fmt.Errorf("mouting %s as bind %s", rootfs, err) } - if err := mountSystem(rootfs, MountConfig); err != nil { + if err := mountSystem(rootfs, mountConfig); err != nil { return fmt.Errorf("mount system %s", err) } - if err := setupBindmounts(rootfs, MountConfig.Mounts); err != nil { + if err := setupBindmounts(rootfs, mountConfig.Mounts); err != nil { return fmt.Errorf("bind mounts %s", err) } - if err := nodes.CreateDeviceNodes(rootfs, MountConfig.DeviceNodes); err != nil { + if err := nodes.CreateDeviceNodes(rootfs, mountConfig.DeviceNodes); err != nil { return fmt.Errorf("create device nodes %s", err) } - if err := SetupPtmx(rootfs, console, MountConfig.MountLabel); err != nil { + if err := SetupPtmx(rootfs, console, mountConfig.MountLabel); err != nil { return err } if err := setupDevSymlinks(rootfs); err != nil { @@ -60,7 +60,7 @@ func InitializeMountNamespace(rootfs, console string, MountConfig *MountConfig) return fmt.Errorf("chdir into %s %s", rootfs, err) } - if MountConfig.NoPivotRoot { + if mountConfig.NoPivotRoot { err = MsMoveRoot(rootfs) } else { err = PivotRoot(rootfs) @@ -69,7 +69,7 @@ func InitializeMountNamespace(rootfs, console string, MountConfig *MountConfig) return err } - if MountConfig.ReadonlyFs { + if mountConfig.ReadonlyFs { if err := SetReadonly(); err != nil { return fmt.Errorf("set readonly %s", err) } @@ -82,8 +82,8 @@ func InitializeMountNamespace(rootfs, console string, MountConfig *MountConfig) // mountSystem sets up linux specific system mounts like sys, proc, shm, and devpts // inside the mount namespace -func mountSystem(rootfs string, MountConfig *MountConfig) error { - for _, m := range newSystemMounts(rootfs, MountConfig.MountLabel, MountConfig.Mounts) { +func mountSystem(rootfs string, mountConfig *MountConfig) error { + for _, m := range newSystemMounts(rootfs, mountConfig.MountLabel, mountConfig.Mounts) { if err := os.MkdirAll(m.path, 0755); err != nil && !os.IsExist(err) { return fmt.Errorf("mkdirall %s %s", m.path, err) } diff --git a/mount/types.go b/mount/types.go index 54586e7ef..9a0083705 100644 --- a/mount/types.go +++ b/mount/types.go @@ -21,7 +21,7 @@ type MountConfig struct { // The device nodes that should be automatically created within the container upon container start. Note, make sure that the node is marked as allowed in the cgroup as well! DeviceNodes []*devices.Device `json:"device_nodes,omitempty"` - MountLabel string + MountLabel string `json:"mount_label,omitempty"` } type Mount struct { From ad5286acd91f26140978c3eb787741477371419c Mon Sep 17 00:00:00 2001 From: Vishnu Kannan Date: Mon, 23 Jun 2014 20:40:37 +0000 Subject: [PATCH 07/12] Addressed more comments. Docker-DCO-1.1-Signed-off-by: Vishnu Kannan (github: vishh) --- container.go | 3 +-- namespaces/exec.go | 2 +- namespaces/init.go | 2 +- network/types.go | 6 +++--- utils.go | 11 ++--------- 5 files changed, 8 insertions(+), 16 deletions(-) diff --git a/container.go b/container.go index 05d0a84b2..88c3e23b1 100644 --- a/container.go +++ b/container.go @@ -6,10 +6,9 @@ import ( "github.com/docker/libcontainer/mount" ) -// Reusing internal Mount struct since we don't expect the API and the internal representation to differ much in the future. type Mount mount.Mount -type Mounts []Mount +type Mounts mount.Mounts type Network struct { // Type sets the networks type, commonly veth and loopback diff --git a/namespaces/exec.go b/namespaces/exec.go index 0b5d4f5ec..2cc859c6f 100644 --- a/namespaces/exec.go +++ b/namespaces/exec.go @@ -157,7 +157,7 @@ func InitializeNetworking(container *libcontainer.Container, nspid int, pipe *Sy if err != nil { return err } - if err := strategy.Create(libcontainer.GetInternalNetworkSpec(config), nspid, context); err != nil { + if err := strategy.Create(libcontainer.GetInternalNetworkConfig(config), nspid, context); err != nil { return err } } diff --git a/namespaces/init.go b/namespaces/init.go index 8ea4ef697..7385067b5 100644 --- a/namespaces/init.go +++ b/namespaces/init.go @@ -166,7 +166,7 @@ func setupNetwork(container *libcontainer.Container, context map[string]string) return err } - err1 := strategy.Initialize(libcontainer.GetInternalNetworkSpec(config), context) + err1 := strategy.Initialize(libcontainer.GetInternalNetworkConfig(config), context) if err1 != nil { return err1 } diff --git a/network/types.go b/network/types.go index 6a7fe3ee1..e4ebbb2b8 100644 --- a/network/types.go +++ b/network/types.go @@ -9,13 +9,13 @@ type Network struct { Type string `json:"type,omitempty"` // Path to network namespace - NsPath string + NsPath string `json:"ns_path,omitempty"` // The bridge to use. - Bridge string + Bridge string `json:"bridge,omitempty"` // Prefix for the veth interfaces. - VethPrefix string + VethPrefix string `json:"type,omitempty"` // Address contains the IP and mask to set on the network interface Address string `json:"address,omitempty"` diff --git a/utils.go b/utils.go index a4e2e8844..3ba66a91f 100644 --- a/utils.go +++ b/utils.go @@ -12,19 +12,12 @@ func GetInternalMountConfig(container *Container) *mount.MountConfig { ReadonlyFs: container.ReadonlyFs, DeviceNodes: container.DeviceNodes, MountLabel: container.Context["mount_label"], - } - for _, mountFromSpec := range container.Mounts { - out.Mounts = append(out.Mounts, mount.Mount{ - Type: mountFromSpec.Type, - Source: mountFromSpec.Source, - Destination: mountFromSpec.Destination, - Writable: mountFromSpec.Writable, - Private: mountFromSpec.Private}) + Mounts: (mount.Mounts)(container.Mounts), } return out } -func GetInternalNetworkSpec(net *Network) *network.Network { +func GetInternalNetworkConfig(net *Network) *network.Network { return &network.Network{ Type: net.Type, NsPath: net.Context["nspath"], From 952b88488247cf7ad2124db49d7aded6383c9240 Mon Sep 17 00:00:00 2001 From: Vishnu Kannan Date: Mon, 23 Jun 2014 21:11:01 +0000 Subject: [PATCH 08/12] Use internal types in the API instead of duplicating the types. Docker-DCO-1.1-Signed-off-by: Vishnu Kannan (github: vishh) --- container.go | 41 +++++------------------------------------ namespaces/exec.go | 2 +- namespaces/init.go | 6 ++++-- utils.go | 25 ------------------------- 4 files changed, 10 insertions(+), 64 deletions(-) diff --git a/container.go b/container.go index 88c3e23b1..952c93bde 100644 --- a/container.go +++ b/container.go @@ -2,49 +2,18 @@ package libcontainer import ( "github.com/docker/libcontainer/cgroups" - "github.com/docker/libcontainer/devices" "github.com/docker/libcontainer/mount" + "github.com/docker/libcontainer/network" ) -type Mount mount.Mount +type MountConfig mount.MountConfig -type Mounts mount.Mounts - -type Network struct { - // Type sets the networks type, commonly veth and loopback - Type string `json:"type,omitempty"` - - // Context is a generic key value format for setting additional options that are specific to - // the network type - Context map[string]string `json:"context,omitempty"` - - // Address contains the IP and mask to set on the network interface - Address string `json:"address,omitempty"` - - // Gateway sets the gateway address that is used as the default for the interface - Gateway string `json:"gateway,omitempty"` - - // Mtu sets the mtu value for the interface and will be mirrored on both the host and - // container's interfaces if a pair is created, specifically in the case of type veth - Mtu int `json:"mtu,omitempty"` -} +type Network network.Network // Container defines configuration options for executing a process inside a contained environment type Container struct { - // NoPivotRoot will use MS_MOVE and a chroot to jail the process into the container's rootfs - // This is a common option when the container is running in ramdisk - NoPivotRoot bool `json:"no_pivot_root,omitempty"` - - // ReadonlyFs will remount the container's rootfs as readonly where only externally mounted - // bind mounts are writtable - ReadonlyFs bool `json:"readonly_fs,omitempty"` - - // Mounts specify additional source and destination paths that will be mounted inside the container's - // rootfs and mount namespace if specified - Mounts Mounts `json:"mounts,omitempty"` - - // The device nodes that should be automatically created within the container upon container start. Note, make sure that the node is marked as allowed in the cgroup as well! - DeviceNodes []*devices.Device `json:"device_nodes,omitempty"` + // Mount specific options. + MountConfig MountConfig `json:"mount_config,omitempty"` // Hostname optionally sets the container's hostname if provided Hostname string `json:"hostname,omitempty"` diff --git a/namespaces/exec.go b/namespaces/exec.go index 2cc859c6f..297de529b 100644 --- a/namespaces/exec.go +++ b/namespaces/exec.go @@ -157,7 +157,7 @@ func InitializeNetworking(container *libcontainer.Container, nspid int, pipe *Sy if err != nil { return err } - if err := strategy.Create(libcontainer.GetInternalNetworkConfig(config), nspid, context); err != nil { + if err := strategy.Create((*network.Network)(config), nspid, context); err != nil { return err } } diff --git a/namespaces/init.go b/namespaces/init.go index 7385067b5..a0ce7b721 100644 --- a/namespaces/init.go +++ b/namespaces/init.go @@ -69,7 +69,9 @@ func Init(container *libcontainer.Container, uncleanRootfs, consolePath string, label.Init() - if err := mount.InitializeMountNamespace(rootfs, consolePath, libcontainer.GetInternalMountConfig(container)); err != nil { + if err := mount.InitializeMountNamespace(rootfs, + consolePath, + (*mount.MountConfig)(&container.MountConfig)); err != nil { return fmt.Errorf("setup mount namespace %s", err) } if container.Hostname != "" { @@ -166,7 +168,7 @@ func setupNetwork(container *libcontainer.Container, context map[string]string) return err } - err1 := strategy.Initialize(libcontainer.GetInternalNetworkConfig(config), context) + err1 := strategy.Initialize((*network.Network)(config), context) if err1 != nil { return err1 } diff --git a/utils.go b/utils.go index 3ba66a91f..ab770848b 100644 --- a/utils.go +++ b/utils.go @@ -1,34 +1,9 @@ package libcontainer import ( - "github.com/docker/libcontainer/mount" - "github.com/docker/libcontainer/network" "github.com/docker/libcontainer/security/capabilities" ) -func GetInternalMountConfig(container *Container) *mount.MountConfig { - out := &mount.MountConfig{ - NoPivotRoot: container.NoPivotRoot, - ReadonlyFs: container.ReadonlyFs, - DeviceNodes: container.DeviceNodes, - MountLabel: container.Context["mount_label"], - Mounts: (mount.Mounts)(container.Mounts), - } - return out -} - -func GetInternalNetworkConfig(net *Network) *network.Network { - return &network.Network{ - Type: net.Type, - NsPath: net.Context["nspath"], - Bridge: net.Context["bridge"], - VethPrefix: net.Context["prefix"], - Address: net.Address, - Gateway: net.Gateway, - Mtu: net.Mtu, - } -} - func GetAllCapabilities() []string { return capabilities.GetAllCapabilities() } From f216ad7b65d21df46203763ae03d92f9be4533bc Mon Sep 17 00:00:00 2001 From: Vishnu Kannan Date: Mon, 23 Jun 2014 21:11:01 +0000 Subject: [PATCH 09/12] Use internal types in the API instead of duplicating the types. Docker-DCO-1.1-Signed-off-by: Vishnu Kannan (github: vishh) --- utils.go | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100644 utils.go diff --git a/utils.go b/utils.go deleted file mode 100644 index ab770848b..000000000 --- a/utils.go +++ /dev/null @@ -1,17 +0,0 @@ -package libcontainer - -import ( - "github.com/docker/libcontainer/security/capabilities" -) - -func GetAllCapabilities() []string { - return capabilities.GetAllCapabilities() -} - -func DropBoundingSet(container *Container) error { - return capabilities.DropBoundingSet(container.Capabilities) -} - -func DropCapabilities(container *Container) error { - return capabilities.DropCapabilities(container.Capabilities) -} From 1aff270a6c0174677958cd6b8f2339971b2a5939 Mon Sep 17 00:00:00 2001 From: Michael Crosby Date: Mon, 23 Jun 2014 15:19:14 -0700 Subject: [PATCH 10/12] Fix veth json and tags Docker-DCO-1.1-Signed-off-by: Michael Crosby (github: crosbymichael) --- container_test.go | 31 ++++++++++++++++++++++++++++ network/types.go | 2 +- sample_configs/attach_to_bridge.json | 6 ++---- 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/container_test.go b/container_test.go index a0008f35f..cfbbcca4a 100644 --- a/container_test.go +++ b/container_test.go @@ -61,4 +61,35 @@ func TestContainerJsonFormat(t *testing.T) { t.Log("capabilities mask should contain SYS_CHROOT") t.Fail() } + + for _, n := range container.Networks { + if n.Type == "veth" { + if n.Bridge != "docker0" { + t.Logf("veth bridge should be docker0 but received %q", n.Bridge) + t.Fail() + } + + if n.Address != "172.17.0.101/16" { + t.Logf("veth address should be 172.17.0.101/61 but received %q", n.Address) + t.Fail() + } + + if n.VethPrefix != "veth" { + t.Logf("veth prefix should be veth but received %q", n.VethPrefix) + t.Fail() + } + + if n.Gateway != "172.17.42.1" { + t.Logf("veth gateway should be 172.17.42.1 but received %q", n.Gateway) + t.Fail() + } + + if n.Mtu != 1500 { + t.Logf("veth mtu should be 1500 but received %d", n.Mtu) + t.Fail() + } + + break + } + } } diff --git a/network/types.go b/network/types.go index e4ebbb2b8..14463ab71 100644 --- a/network/types.go +++ b/network/types.go @@ -15,7 +15,7 @@ type Network struct { Bridge string `json:"bridge,omitempty"` // Prefix for the veth interfaces. - VethPrefix string `json:"type,omitempty"` + VethPrefix string `json:"veth_prefix,omitempty"` // Address contains the IP and mask to set on the network interface Address string `json:"address,omitempty"` diff --git a/sample_configs/attach_to_bridge.json b/sample_configs/attach_to_bridge.json index da138d173..20547fe13 100644 --- a/sample_configs/attach_to_bridge.json +++ b/sample_configs/attach_to_bridge.json @@ -200,10 +200,8 @@ }, { "address": "172.17.0.101/16", - "context": { - "bridge": "docker0", - "prefix": "veth" - }, + "bridge": "docker0", + "veth_prefix": "veth", "gateway": "172.17.42.1", "mtu": 1500, "type": "veth" From 0023305afcad012ea0e93dd8905fd42d3b098016 Mon Sep 17 00:00:00 2001 From: Michael Crosby Date: Mon, 23 Jun 2014 15:28:43 -0700 Subject: [PATCH 11/12] Make MountConfig on container a pointer Also add unit test for container json files to ensure that the mount config is read and device nodes are validated. Docker-DCO-1.1-Signed-off-by: Michael Crosby (github: crosbymichael) --- container.go | 2 +- container_test.go | 23 ++++++ namespaces/init.go | 2 +- sample_configs/attach_to_bridge.json | 109 +++++++++++++-------------- sample_configs/minimal.json | 100 ++++++++++++------------ 5 files changed, 128 insertions(+), 108 deletions(-) diff --git a/container.go b/container.go index 952c93bde..e3ade00b4 100644 --- a/container.go +++ b/container.go @@ -13,7 +13,7 @@ type Network network.Network // Container defines configuration options for executing a process inside a contained environment type Container struct { // Mount specific options. - MountConfig MountConfig `json:"mount_config,omitempty"` + MountConfig *MountConfig `json:"mount_config,omitempty"` // Hostname optionally sets the container's hostname if provided Hostname string `json:"hostname,omitempty"` diff --git a/container_test.go b/container_test.go index cfbbcca4a..c70405652 100644 --- a/container_test.go +++ b/container_test.go @@ -4,6 +4,8 @@ import ( "encoding/json" "os" "testing" + + "github.com/docker/libcontainer/devices" ) // Checks whether the expected capability is specified in the capabilities. @@ -16,6 +18,20 @@ func contains(expected string, values []string) bool { return false } +func containsDevice(expected *devices.Device, values []*devices.Device) bool { + for _, d := range values { + if d.Path == expected.Path && + d.CgroupPermissions == expected.CgroupPermissions && + d.FileMode == expected.FileMode && + d.MajorNumber == expected.MajorNumber && + d.MinorNumber == expected.MinorNumber && + d.Type == expected.Type { + return true + } + } + return false +} + func TestContainerJsonFormat(t *testing.T) { f, err := os.Open("sample_configs/attach_to_bridge.json") if err != nil { @@ -92,4 +108,11 @@ func TestContainerJsonFormat(t *testing.T) { break } } + + for _, d := range devices.DefaultSimpleDevices { + if !containsDevice(d, container.MountConfig.DeviceNodes) { + t.Logf("expected defice configuration for %s", d.Path) + t.Fail() + } + } } diff --git a/namespaces/init.go b/namespaces/init.go index a0ce7b721..905889ea3 100644 --- a/namespaces/init.go +++ b/namespaces/init.go @@ -71,7 +71,7 @@ func Init(container *libcontainer.Container, uncleanRootfs, consolePath string, if err := mount.InitializeMountNamespace(rootfs, consolePath, - (*mount.MountConfig)(&container.MountConfig)); err != nil { + (*mount.MountConfig)(container.MountConfig)); err != nil { return fmt.Errorf("setup mount namespace %s", err) } if container.Hostname != "" { diff --git a/sample_configs/attach_to_bridge.json b/sample_configs/attach_to_bridge.json index 20547fe13..9b1e627d9 100644 --- a/sample_configs/attach_to_bridge.json +++ b/sample_configs/attach_to_bridge.json @@ -121,66 +121,61 @@ "process_label": "", "restrictions": "true" }, - "device_nodes": [ - { - "cgroup_permissions": "rwm", - "major_number": 10, - "minor_number": 229, - "path": "/dev/fuse", - "type": 99 - }, - { - "cgroup_permissions": "rwm", - "file_mode": 438, - "major_number": 1, - "minor_number": 3, - "path": "/dev/null", - "type": 99 - }, - { - "cgroup_permissions": "rwm", - "file_mode": 438, - "major_number": 1, - "minor_number": 5, - "path": "/dev/zero", - "type": 99 - }, - { - "cgroup_permissions": "rwm", - "file_mode": 438, - "major_number": 1, - "minor_number": 7, - "path": "/dev/full", - "type": 99 - }, - { - "cgroup_permissions": "rwm", - "file_mode": 438, - "major_number": 5, - "path": "/dev/tty", - "type": 99 - }, - { - "cgroup_permissions": "rwm", - "file_mode": 438, - "major_number": 1, - "minor_number": 9, - "path": "/dev/urandom", - "type": 99 - }, - { - "cgroup_permissions": "rwm", - "file_mode": 438, - "major_number": 1, - "minor_number": 8, - "path": "/dev/random", - "type": 99 - } - ], + "mount_config": { + "device_nodes": [ + { + "cgroup_permissions": "rwm", + "file_mode": 438, + "major_number": 1, + "minor_number": 3, + "path": "/dev/null", + "type": 99 + }, + { + "cgroup_permissions": "rwm", + "file_mode": 438, + "major_number": 1, + "minor_number": 5, + "path": "/dev/zero", + "type": 99 + }, + { + "cgroup_permissions": "rwm", + "file_mode": 438, + "major_number": 1, + "minor_number": 7, + "path": "/dev/full", + "type": 99 + }, + { + "cgroup_permissions": "rwm", + "file_mode": 438, + "major_number": 5, + "path": "/dev/tty", + "type": 99 + }, + { + "cgroup_permissions": "rwm", + "file_mode": 438, + "major_number": 1, + "minor_number": 9, + "path": "/dev/urandom", + "type": 99 + }, + { + "cgroup_permissions": "rwm", + "file_mode": 438, + "major_number": 1, + "minor_number": 8, + "path": "/dev/random", + "type": 99 + } + ] + }, "environment": [ "HOME=/", "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", - "HOSTNAME=2d388ea3bd92", + "HOSTNAME=koye", "TERM=xterm" ], "hostname": "koye", diff --git a/sample_configs/minimal.json b/sample_configs/minimal.json index b0f6ffc08..3e1a01ad0 100644 --- a/sample_configs/minimal.json +++ b/sample_configs/minimal.json @@ -121,55 +121,57 @@ "process_label": "", "restrictions": "true" }, - "device_nodes": [ - { - "cgroup_permissions": "rwm", - "file_mode": 438, - "major_number": 1, - "minor_number": 3, - "path": "/dev/null", - "type": 99 - }, - { - "cgroup_permissions": "rwm", - "file_mode": 438, - "major_number": 1, - "minor_number": 5, - "path": "/dev/zero", - "type": 99 - }, - { - "cgroup_permissions": "rwm", - "file_mode": 438, - "major_number": 1, - "minor_number": 7, - "path": "/dev/full", - "type": 99 - }, - { - "cgroup_permissions": "rwm", - "file_mode": 438, - "major_number": 5, - "path": "/dev/tty", - "type": 99 - }, - { - "cgroup_permissions": "rwm", - "file_mode": 438, - "major_number": 1, - "minor_number": 9, - "path": "/dev/urandom", - "type": 99 - }, - { - "cgroup_permissions": "rwm", - "file_mode": 438, - "major_number": 1, - "minor_number": 8, - "path": "/dev/random", - "type": 99 - } - ], + "mount_config": { + "device_nodes": [ + { + "cgroup_permissions": "rwm", + "file_mode": 438, + "major_number": 1, + "minor_number": 3, + "path": "/dev/null", + "type": 99 + }, + { + "cgroup_permissions": "rwm", + "file_mode": 438, + "major_number": 1, + "minor_number": 5, + "path": "/dev/zero", + "type": 99 + }, + { + "cgroup_permissions": "rwm", + "file_mode": 438, + "major_number": 1, + "minor_number": 7, + "path": "/dev/full", + "type": 99 + }, + { + "cgroup_permissions": "rwm", + "file_mode": 438, + "major_number": 5, + "path": "/dev/tty", + "type": 99 + }, + { + "cgroup_permissions": "rwm", + "file_mode": 438, + "major_number": 1, + "minor_number": 9, + "path": "/dev/urandom", + "type": 99 + }, + { + "cgroup_permissions": "rwm", + "file_mode": 438, + "major_number": 1, + "minor_number": 8, + "path": "/dev/random", + "type": 99 + } + ] + }, "environment": [ "HOME=/", "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", From d2c7999a572a19d49093dffacf97b6b5076f3bc8 Mon Sep 17 00:00:00 2001 From: Michael Crosby Date: Mon, 23 Jun 2014 16:23:51 -0700 Subject: [PATCH 12/12] Fix cross compile for network and node pkgs Docker-DCO-1.1-Signed-off-by: Michael Crosby (github: crosbymichael) --- mount/nodes/nodes_unsupported.go | 4 +++- namespaces/unsupported.go | 1 + network/loopback.go | 2 ++ network/netns.go | 2 ++ network/network.go | 5 ++++- network/strategy.go | 2 ++ network/veth.go | 2 ++ 7 files changed, 16 insertions(+), 2 deletions(-) diff --git a/mount/nodes/nodes_unsupported.go b/mount/nodes/nodes_unsupported.go index 00e59eb34..83660715d 100644 --- a/mount/nodes/nodes_unsupported.go +++ b/mount/nodes/nodes_unsupported.go @@ -3,9 +3,11 @@ package nodes import ( + "errors" + "github.com/docker/libcontainer/devices" ) func CreateDeviceNodes(rootfs string, nodesToCreate []*devices.Device) error { - return ErrUnsupported + return errors.New("Unsupported method") } diff --git a/namespaces/unsupported.go b/namespaces/unsupported.go index 5fa8832a3..9c44b658e 100644 --- a/namespaces/unsupported.go +++ b/namespaces/unsupported.go @@ -3,6 +3,7 @@ package namespaces import ( + "github.com/docker/libcontainer" "github.com/docker/libcontainer/cgroups" ) diff --git a/network/loopback.go b/network/loopback.go index 284a4e65f..0d36c4f8c 100644 --- a/network/loopback.go +++ b/network/loopback.go @@ -1,3 +1,5 @@ +// +build linux + package network import ( diff --git a/network/netns.go b/network/netns.go index 4d132e7c7..e2121cb08 100644 --- a/network/netns.go +++ b/network/netns.go @@ -1,3 +1,5 @@ +// +build linux + package network import ( diff --git a/network/network.go b/network/network.go index 94cd711d2..48eeec604 100644 --- a/network/network.go +++ b/network/network.go @@ -1,8 +1,11 @@ +// +build linux + package network import ( - "github.com/docker/libcontainer/netlink" "net" + + "github.com/docker/libcontainer/netlink" ) func InterfaceUp(name string) error { diff --git a/network/strategy.go b/network/strategy.go index 00813f6b7..358fb4152 100644 --- a/network/strategy.go +++ b/network/strategy.go @@ -1,3 +1,5 @@ +// +build linux + package network import ( diff --git a/network/veth.go b/network/veth.go index 817144fa2..20bc9e506 100644 --- a/network/veth.go +++ b/network/veth.go @@ -1,3 +1,5 @@ +// +build linux + package network import (