Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move docker init into drivers functions #2

Merged
merged 1 commit into from
Jan 15, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
22 changes: 21 additions & 1 deletion execdriver/chroot/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,29 @@ package chroot

import (
"github.com/dotcloud/docker/execdriver"
"github.com/dotcloud/docker/mount"
"os"
"os/exec"
)

const DriverName = "chroot"

func init() {
execdriver.RegisterDockerInitFct(DriverName, func(args *execdriver.DockerInitArgs) error {
if err := mount.ForceMount("proc", "proc", "proc", ""); err != nil {
return err
}
defer mount.ForceUnmount("proc")
cmd := exec.Command(args.Args[0], args.Args[1:]...)

cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdout
cmd.Stdin = os.Stdin

return cmd.Run()
})
}

type driver struct {
}

Expand All @@ -13,7 +33,7 @@ func NewDriver() (*driver, error) {
}

func (d *driver) Name() string {
return "chroot"
return DriverName
}

func (d *driver) Run(c *execdriver.Process, startCallback execdriver.StartCallback) (int, error) {
Expand Down
44 changes: 41 additions & 3 deletions execdriver/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,49 @@ import (
)

var (
ErrNotRunning = errors.New("Process could not be started")
ErrWaitTimeoutReached = errors.New("Wait timeout reached")
ErrNotRunning = errors.New("Process could not be started")
ErrWaitTimeoutReached = errors.New("Wait timeout reached")
ErrDriverAlreadyRegistered = errors.New("A driver already registered this docker init function")
ErrDriverNotFound = errors.New("The requested docker init has not been found")
)

type StartCallback func(*Process)
var dockerInitFcts map[string]DockerInitFct

type (
StartCallback func(*Process)
DockerInitFct func(i *DockerInitArgs) error
)

func RegisterDockerInitFct(name string, fct DockerInitFct) error {
if dockerInitFcts == nil {
dockerInitFcts = make(map[string]DockerInitFct)
}
if _, ok := dockerInitFcts[name]; ok {
return ErrDriverAlreadyRegistered
}
dockerInitFcts[name] = fct
return nil
}

func GetDockerInitFct(name string) (DockerInitFct, error) {
fct, ok := dockerInitFcts[name]
if !ok {
return nil, ErrDriverNotFound
}
return fct, nil
}

type DockerInitArgs struct {
User string
Gateway string
Ip string
WorkDir string
Privileged bool
Env []string
Args []string
Mtu int
Driver string
}

type Driver interface {
Run(c *Process, startCallback StartCallback) (int, error) // Run executes the process and blocks until the process exits and returns the exit code
Expand Down
38 changes: 37 additions & 1 deletion execdriver/lxc/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,50 @@ import (
"github.com/dotcloud/docker/execdriver"
"github.com/dotcloud/docker/utils"
"io/ioutil"
"log"
"os"
"os/exec"
"path"
"strconv"
"strings"
"syscall"
"time"
)

const DriverName = "lxc"

func init() {
execdriver.RegisterDockerInitFct(DriverName, func(args *execdriver.DockerInitArgs) error {
if err := setupHostname(args); err != nil {
return err
}

if err := setupNetworking(args); err != nil {
return err
}

if err := setupCapabilities(args); err != nil {
return err
}
if err := setupWorkingDirectory(args); err != nil {
return err
}

if err := changeUser(args); err != nil {
return err
}
path, err := exec.LookPath(args.Args[0])
if err != nil {
log.Printf("Unable to locate %v", args.Args[0])
os.Exit(127)
}
if err := syscall.Exec(path, args.Args, os.Environ()); err != nil {
panic(err)
}
panic("Unreachable")
})
}

type driver struct {
root string // root path for the driver to use
apparmor bool
Expand All @@ -32,7 +68,7 @@ func NewDriver(root string, apparmor bool) (*driver, error) {
}

func (d *driver) Name() string {
return "lxc"
return DriverName
}

func (d *driver) Run(c *execdriver.Process, startCallback execdriver.StartCallback) (int, error) {
Expand Down
153 changes: 153 additions & 0 deletions execdriver/lxc/init.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
package lxc

import (
"fmt"
"github.com/dotcloud/docker/execdriver"
"github.com/dotcloud/docker/pkg/netlink"
"github.com/dotcloud/docker/utils"
"github.com/syndtr/gocapability/capability"
"net"
"os"
"strconv"
"strings"
"syscall"
)

func setupHostname(args *execdriver.DockerInitArgs) error {
hostname := getEnv(args, "HOSTNAME")
if hostname == "" {
return nil
}
return setHostname(hostname)
}

// Setup networking
func setupNetworking(args *execdriver.DockerInitArgs) error {
if args.Ip != "" {
// eth0
iface, err := net.InterfaceByName("eth0")
if err != nil {
return fmt.Errorf("Unable to set up networking: %v", err)
}
ip, ipNet, err := net.ParseCIDR(args.Ip)
if err != nil {
return fmt.Errorf("Unable to set up networking: %v", err)
}
if err := netlink.NetworkLinkAddIp(iface, ip, ipNet); err != nil {
return fmt.Errorf("Unable to set up networking: %v", err)
}
if err := netlink.NetworkSetMTU(iface, args.Mtu); err != nil {
return fmt.Errorf("Unable to set MTU: %v", err)
}
if err := netlink.NetworkLinkUp(iface); err != nil {
return fmt.Errorf("Unable to set up networking: %v", err)
}

// loopback
iface, err = net.InterfaceByName("lo")
if err != nil {
return fmt.Errorf("Unable to set up networking: %v", err)
}
if err := netlink.NetworkLinkUp(iface); err != nil {
return fmt.Errorf("Unable to set up networking: %v", err)
}
}
if args.Gateway != "" {
gw := net.ParseIP(args.Gateway)
if gw == nil {
return fmt.Errorf("Unable to set up networking, %s is not a valid gateway IP", args.Gateway)
}

if err := netlink.AddDefaultGw(gw); err != nil {
return fmt.Errorf("Unable to set up networking: %v", err)
}
}

return nil
}

// Setup working directory
func setupWorkingDirectory(args *execdriver.DockerInitArgs) error {
if args.WorkDir == "" {
return nil
}
if err := syscall.Chdir(args.WorkDir); err != nil {
return fmt.Errorf("Unable to change dir to %v: %v", args.WorkDir, err)
}
return nil
}

// Takes care of dropping privileges to the desired user
func changeUser(args *execdriver.DockerInitArgs) error {
if args.User == "" {
return nil
}
userent, err := utils.UserLookup(args.User)
if err != nil {
return fmt.Errorf("Unable to find user %v: %v", args.User, err)
}

uid, err := strconv.Atoi(userent.Uid)
if err != nil {
return fmt.Errorf("Invalid uid: %v", userent.Uid)
}
gid, err := strconv.Atoi(userent.Gid)
if err != nil {
return fmt.Errorf("Invalid gid: %v", userent.Gid)
}

if err := syscall.Setgid(gid); err != nil {
return fmt.Errorf("setgid failed: %v", err)
}
if err := syscall.Setuid(uid); err != nil {
return fmt.Errorf("setuid failed: %v", err)
}

return nil
}

func setupCapabilities(args *execdriver.DockerInitArgs) error {

if args.Privileged {
return nil
}

drop := []capability.Cap{
capability.CAP_SETPCAP,
capability.CAP_SYS_MODULE,
capability.CAP_SYS_RAWIO,
capability.CAP_SYS_PACCT,
capability.CAP_SYS_ADMIN,
capability.CAP_SYS_NICE,
capability.CAP_SYS_RESOURCE,
capability.CAP_SYS_TIME,
capability.CAP_SYS_TTY_CONFIG,
capability.CAP_MKNOD,
capability.CAP_AUDIT_WRITE,
capability.CAP_AUDIT_CONTROL,
capability.CAP_MAC_OVERRIDE,
capability.CAP_MAC_ADMIN,
}

c, err := capability.NewPid(os.Getpid())
if err != nil {
return err
}

c.Unset(capability.CAPS|capability.BOUNDS, drop...)

if err := c.Apply(capability.CAPS | capability.BOUNDS); err != nil {
return err
}
return nil
}

func getEnv(args *execdriver.DockerInitArgs, key string) string {
for _, kv := range args.Env {
parts := strings.SplitN(kv, "=", 2)
if parts[0] == key && len(parts) == 2 {
return parts[1]
}
}
return ""
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package sysinit
package lxc

func setHostname(hostname string) error {
panic("Not supported on darwin")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package sysinit
package lxc

import (
"syscall"
Expand Down