pass all environment from ./oz to applications launched from oz-init

(+ gofmt)
master
brl 10 years ago
parent dee514bd4e
commit d1bb0fdeec

@ -51,7 +51,7 @@ func ListSandboxes() ([]SandboxInfo, error) {
return body.Sandboxes, nil return body.Sandboxes, nil
} }
func Launch(arg string) error { func Launch(arg string, env []string) error {
idx, name, err := parseProfileArg(arg) idx, name, err := parseProfileArg(arg)
if err != nil { if err != nil {
return err return err
@ -59,6 +59,7 @@ func Launch(arg string) error {
resp, err := clientSend(&LaunchMsg{ resp, err := clientSend(&LaunchMsg{
Index: idx, Index: idx,
Name: name, Name: name,
Env: env,
}) })
if err != nil { if err != nil {
return err return err

@ -9,7 +9,7 @@ import (
"github.com/subgraph/oz/fs" "github.com/subgraph/oz/fs"
"github.com/subgraph/oz/ipc" "github.com/subgraph/oz/ipc"
"github.com/subgraph/oz/network" "github.com/subgraph/oz/network"
"github.com/op/go-logging" "github.com/op/go-logging"
) )
@ -62,7 +62,7 @@ func initialize() *daemonState {
oz.ReapChildProcs(d.log, d.handleChildExit) oz.ReapChildProcs(d.log, d.handleChildExit)
d.nextSboxId = 1 d.nextSboxId = 1
d.nextDisplay = 100 d.nextDisplay = 100
for _, pp := range d.profiles { for _, pp := range d.profiles {
if pp.Networking.Nettype == "bridge" { if pp.Networking.Nettype == "bridge" {
d.log.Info("Initializing bridge networking") d.log.Info("Initializing bridge networking")
@ -71,12 +71,12 @@ func initialize() *daemonState {
d.log.Fatalf("Failed to initialize bridge networking: %+v", err) d.log.Fatalf("Failed to initialize bridge networking: %+v", err)
return nil return nil
} }
d.network = htn d.network = htn
network.NetPrint(d.log) network.NetPrint(d.log)
break; break
} }
} }
@ -125,7 +125,7 @@ func (d *daemonState) handleLaunch(msg *LaunchMsg, m *ipc.Message) error {
return m.Respond(&ErrorMsg{err.Error()}) return m.Respond(&ErrorMsg{err.Error()})
} }
d.Debug("Would launch %s", p.Name) d.Debug("Would launch %s", p.Name)
_, err = d.launch(p, m.Ucred.Uid, m.Ucred.Gid, d.log) _, err = d.launch(p, msg.Env, m.Ucred.Uid, m.Ucred.Gid, d.log)
if err != nil { if err != nil {
d.Warning("launch of %s failed: %v", p.Name, err) d.Warning("launch of %s failed: %v", p.Name, err)
return m.Respond(&ErrorMsg{err.Error()}) return m.Respond(&ErrorMsg{err.Error()})

@ -9,13 +9,14 @@ import (
"path" "path"
"sync" "sync"
"syscall" "syscall"
"github.com/subgraph/oz" "github.com/subgraph/oz"
"github.com/subgraph/oz/fs" "github.com/subgraph/oz/fs"
"github.com/subgraph/oz/xpra"
"github.com/subgraph/oz/network" "github.com/subgraph/oz/network"
"github.com/subgraph/oz/xpra"
"github.com/op/go-logging" "github.com/op/go-logging"
"github.com/subgraph/oz/oz-init"
) )
const initPath = "/usr/local/bin/oz-init" const initPath = "/usr/local/bin/oz-init"
@ -46,7 +47,7 @@ func findSandbox(id int) *Sandbox {
} }
*/ */
func createInitCommand(name, chroot string, uid uint32, display int, stn *network.SandboxNetwork, nettype string) *exec.Cmd { func createInitCommand(name, chroot string, env []string, uid uint32, display int, stn *network.SandboxNetwork, nettype string) *exec.Cmd {
cmd := exec.Command(initPath) cmd := exec.Command(initPath)
cmd.Dir = "/" cmd.Dir = "/"
@ -54,11 +55,11 @@ func createInitCommand(name, chroot string, uid uint32, display int, stn *networ
cloneFlags |= syscall.CLONE_NEWIPC cloneFlags |= syscall.CLONE_NEWIPC
cloneFlags |= syscall.CLONE_NEWPID cloneFlags |= syscall.CLONE_NEWPID
cloneFlags |= syscall.CLONE_NEWUTS cloneFlags |= syscall.CLONE_NEWUTS
if nettype != "host" { if nettype != "host" {
cloneFlags |= syscall.CLONE_NEWNET cloneFlags |= syscall.CLONE_NEWNET
} }
cmd.SysProcAttr = &syscall.SysProcAttr{ cmd.SysProcAttr = &syscall.SysProcAttr{
Chroot: chroot, Chroot: chroot,
Cloneflags: cloneFlags, Cloneflags: cloneFlags,
@ -67,20 +68,24 @@ func createInitCommand(name, chroot string, uid uint32, display int, stn *networ
"INIT_PROFILE=" + name, "INIT_PROFILE=" + name,
fmt.Sprintf("INIT_UID=%d", uid), fmt.Sprintf("INIT_UID=%d", uid),
} }
if stn.Ip != "" { if stn.Ip != "" {
cmd.Env = append(cmd.Env, "INIT_ADDR=" + stn.Ip) cmd.Env = append(cmd.Env, "INIT_ADDR="+stn.Ip)
cmd.Env = append(cmd.Env, "INIT_VHOST=" + stn.VethHost) cmd.Env = append(cmd.Env, "INIT_VHOST="+stn.VethHost)
cmd.Env = append(cmd.Env, "INIT_VGUEST=" + stn.VethGuest) cmd.Env = append(cmd.Env, "INIT_VGUEST="+stn.VethGuest)
cmd.Env = append(cmd.Env, "INIT_GATEWAY=" + stn.Gateway.String() + "/" + stn.Class) cmd.Env = append(cmd.Env, "INIT_GATEWAY="+stn.Gateway.String()+"/"+stn.Class)
} }
cmd.Env = append(cmd.Env, fmt.Sprintf("INIT_DISPLAY=%d", display)) cmd.Env = append(cmd.Env, fmt.Sprintf("INIT_DISPLAY=%d", display))
for _, e := range env {
cmd.Env = append(cmd.Env, ozinit.EnvPrefix+e)
}
return cmd return cmd
} }
func (d *daemonState) launch(p *oz.Profile, uid, gid uint32, log *logging.Logger) (*Sandbox, error) { func (d *daemonState) launch(p *oz.Profile, env []string, uid, gid uint32, log *logging.Logger) (*Sandbox, error) {
u, err := user.LookupId(fmt.Sprintf("%d", uid)) u, err := user.LookupId(fmt.Sprintf("%d", uid))
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to lookup user for uid=%d: %v", uid, err) return nil, fmt.Errorf("failed to lookup user for uid=%d: %v", uid, err)
@ -90,11 +95,11 @@ func (d *daemonState) launch(p *oz.Profile, uid, gid uint32, log *logging.Logger
return nil, err return nil, err
} }
display := 0 display := 0
if p.XServer.Enabled && p.Networking.Nettype == "host" { if p.XServer.Enabled && p.Networking.Nettype == "host" {
display = d.nextDisplay display = d.nextDisplay
d.nextDisplay += 1 d.nextDisplay += 1
} }
stn := new(network.SandboxNetwork) stn := new(network.SandboxNetwork)
if p.Networking.Nettype == "bridge" { if p.Networking.Nettype == "bridge" {
stn, err = network.PrepareSandboxNetwork(d.network, log) stn, err = network.PrepareSandboxNetwork(d.network, log)
@ -102,8 +107,8 @@ func (d *daemonState) launch(p *oz.Profile, uid, gid uint32, log *logging.Logger
return nil, fmt.Errorf("Unable to prepare veth network: %+v", err) return nil, fmt.Errorf("Unable to prepare veth network: %+v", err)
} }
} }
cmd := createInitCommand(p.Name, fs.Root(), uid, display, stn, p.Networking.Nettype) cmd := createInitCommand(p.Name, fs.Root(), env, uid, display, stn, p.Networking.Nettype)
log.Debug("Command environment: %+v", cmd.Env) log.Debug("Command environment: %+v", cmd.Env)
pp, err := cmd.StderrPipe() pp, err := cmd.StderrPipe()
if err != nil { if err != nil {
@ -111,13 +116,12 @@ func (d *daemonState) launch(p *oz.Profile, uid, gid uint32, log *logging.Logger
return nil, fmt.Errorf("error creating stderr pipe for init process: %v", err) return nil, fmt.Errorf("error creating stderr pipe for init process: %v", err)
} }
if err := cmd.Start(); err != nil { if err := cmd.Start(); err != nil {
fs.Cleanup() fs.Cleanup()
return nil, fmt.Errorf("Unable to start process: %+v", err) return nil, fmt.Errorf("Unable to start process: %+v", err)
} }
sbox := &Sandbox{ sbox := &Sandbox{
daemon: d, daemon: d,
id: d.nextSboxId, id: d.nextSboxId,
@ -130,7 +134,7 @@ func (d *daemonState) launch(p *oz.Profile, uid, gid uint32, log *logging.Logger
stderr: pp, stderr: pp,
network: stn, network: stn,
} }
if p.Networking.Nettype == "bridge" { if p.Networking.Nettype == "bridge" {
if err := network.NetInit(stn, d.network, cmd.Process.Pid, log); err != nil { if err := network.NetInit(stn, d.network, cmd.Process.Pid, log); err != nil {
cmd.Process.Kill() cmd.Process.Kill()
@ -138,7 +142,7 @@ func (d *daemonState) launch(p *oz.Profile, uid, gid uint32, log *logging.Logger
return nil, fmt.Errorf("Unable to create veth networking: %+v", err) return nil, fmt.Errorf("Unable to create veth networking: %+v", err)
} }
} }
sbox.ready.Add(1) sbox.ready.Add(1)
go sbox.logMessages() go sbox.logMessages()
if sbox.profile.XServer.Enabled { if sbox.profile.XServer.Enabled {

@ -33,6 +33,7 @@ type ListProfilesResp struct {
type LaunchMsg struct { type LaunchMsg struct {
Index int "Launch" Index int "Launch"
Name string Name string
Env []string
} }
type ListSandboxesMsg struct { type ListSandboxesMsg struct {

@ -12,23 +12,25 @@ import (
"strings" "strings"
"sync" "sync"
"syscall" "syscall"
"github.com/subgraph/oz" "github.com/subgraph/oz"
"github.com/subgraph/oz/fs" "github.com/subgraph/oz/fs"
"github.com/subgraph/oz/ipc" "github.com/subgraph/oz/ipc"
"github.com/subgraph/oz/xpra"
"github.com/subgraph/oz/network" "github.com/subgraph/oz/network"
"github.com/subgraph/oz/xpra"
"github.com/kr/pty" "github.com/kr/pty"
"github.com/op/go-logging" "github.com/op/go-logging"
) )
const SocketAddress = "/tmp/oz-init-control" const SocketAddress = "/tmp/oz-init-control"
const EnvPrefix = "INIT_ENV_"
type initState struct { type initState struct {
log *logging.Logger log *logging.Logger
profile *oz.Profile profile *oz.Profile
config *oz.Config config *oz.Config
launchEnv []string
uid int uid int
gid int gid int
user *user.User user *user.User
@ -67,12 +69,12 @@ func parseArgs() *initState {
pname := getvar("INIT_PROFILE") pname := getvar("INIT_PROFILE")
uidval := getvar("INIT_UID") uidval := getvar("INIT_UID")
dispval := os.Getenv("INIT_DISPLAY") dispval := os.Getenv("INIT_DISPLAY")
stnip := os.Getenv("INIT_ADDR") stnip := os.Getenv("INIT_ADDR")
stnvhost := os.Getenv("INIT_VHOST") stnvhost := os.Getenv("INIT_VHOST")
stnvguest := os.Getenv("INIT_VGUEST") stnvguest := os.Getenv("INIT_VGUEST")
stngateway := os.Getenv("INIT_GATEWAY") stngateway := os.Getenv("INIT_GATEWAY")
var config *oz.Config var config *oz.Config
config, err := oz.LoadConfig(oz.DefaultConfigPath) config, err := oz.LoadConfig(oz.DefaultConfigPath)
if err != nil { if err != nil {
@ -109,7 +111,7 @@ func parseArgs() *initState {
} }
display = d display = d
} }
stn := new(network.SandboxNetwork) stn := new(network.SandboxNetwork)
if stnip != "" { if stnip != "" {
gateway, _, err := net.ParseCIDR(stngateway) gateway, _, err := net.ParseCIDR(stngateway)
@ -117,29 +119,39 @@ func parseArgs() *initState {
log.Error("Unable to parse network configuration gateway (%s): %v", stngateway, err) log.Error("Unable to parse network configuration gateway (%s): %v", stngateway, err)
os.Exit(1) os.Exit(1)
} }
stn.Ip = stnip stn.Ip = stnip
stn.VethHost = stnvhost stn.VethHost = stnvhost
stn.VethGuest = stnvguest stn.VethGuest = stnvguest
stn.Gateway = gateway stn.Gateway = gateway
} }
env := []string{}
for _, e := range os.Environ() {
if strings.HasPrefix(e, EnvPrefix) {
e = e[len(EnvPrefix):]
log.Debug("Adding (%s) to launch environment", e)
env = append(env, e)
}
}
return &initState{ return &initState{
log: log, log: log,
config: config, config: config,
profile: p, launchEnv: env,
uid: uid, profile: p,
gid: gid, uid: uid,
user: u, gid: gid,
display: display, user: u,
fs: fs.NewFromProfile(p, u, config.SandboxPath, config.UseFullDev, log), display: display,
network: stn, fs: fs.NewFromProfile(p, u, config.SandboxPath, config.UseFullDev, log),
network: stn,
} }
} }
func (st *initState) runInit() { func (st *initState) runInit() {
st.log.Info("Starting oz-init for profile: %s", st.profile.Name) st.log.Info("Starting oz-init for profile: %s", st.profile.Name)
if st.profile.Networking.Nettype != "host" { if st.profile.Networking.Nettype != "host" {
err := network.NetSetup(st.network) err := network.NetSetup(st.network)
if err != nil { if err != nil {
@ -148,7 +160,7 @@ func (st *initState) runInit() {
} }
} }
network.NetPrint(st.log) network.NetPrint(st.log)
if syscall.Sethostname([]byte(st.profile.Name)) != nil { if syscall.Sethostname([]byte(st.profile.Name)) != nil {
st.log.Error("Failed to set hostname to (%s)", st.profile.Name) st.log.Error("Failed to set hostname to (%s)", st.profile.Name)
} }
@ -159,7 +171,7 @@ func (st *initState) runInit() {
os.Exit(1) os.Exit(1)
} }
oz.ReapChildProcs(st.log, st.handleChildExit) oz.ReapChildProcs(st.log, st.handleChildExit)
if st.profile.XServer.Enabled { if st.profile.XServer.Enabled {
st.xpraReady.Add(1) st.xpraReady.Add(1)
st.startXpraServer() st.startXpraServer()
@ -235,7 +247,7 @@ func (st *initState) readXpraOutput(r io.ReadCloser) {
} }
func (st *initState) launchApplication() { func (st *initState) launchApplication() {
cmd := exec.Command(st.profile.Path + ".unsafe") cmd := exec.Command(st.profile.Path /*+ ".unsafe"*/)
stdout, err := cmd.StdoutPipe() stdout, err := cmd.StdoutPipe()
if err != nil { if err != nil {
st.log.Warning("Failed to create stdout pipe: %v", err) st.log.Warning("Failed to create stdout pipe: %v", err)
@ -251,9 +263,9 @@ func (st *initState) launchApplication() {
Uid: uint32(st.uid), Uid: uint32(st.uid),
Gid: uint32(st.gid), Gid: uint32(st.gid),
} }
cmd.Env = []string{ cmd.Env = append(st.launchEnv,
fmt.Sprintf("DISPLAY=:%d", st.display), fmt.Sprintf("DISPLAY=:%d", st.display),
} )
if err := cmd.Start(); err != nil { if err := cmd.Start(); err != nil {
st.log.Warning("Failed to start application (%s): %v", st.profile.Path, err) st.log.Warning("Failed to start application (%s): %v", st.profile.Path, err)
return return
@ -311,7 +323,7 @@ func (st *initState) handleRunShell(rs *RunShellMsg, msg *ipc.Message) error {
} }
} }
if st.profile.XServer.Enabled { if st.profile.XServer.Enabled {
cmd.Env = append(cmd.Env, "DISPLAY=:" + strconv.Itoa(st.display)) cmd.Env = append(cmd.Env, "DISPLAY=:"+strconv.Itoa(st.display))
} }
cmd.Env = append(cmd.Env, "PATH=/usr/bin:/bin") cmd.Env = append(cmd.Env, "PATH=/usr/bin:/bin")
cmd.Env = append(cmd.Env, fmt.Sprintf("PS1=[%s] $ ", st.profile.Name)) cmd.Env = append(cmd.Env, fmt.Sprintf("PS1=[%s] $ ", st.profile.Name))

@ -71,10 +71,9 @@ func handleLaunch(c *cli.Context) {
fmt.Println("Argument needed to launch command") fmt.Println("Argument needed to launch command")
os.Exit(1) os.Exit(1)
} }
err := daemon.Launch(c.Args()[0]) err := daemon.Launch(c.Args()[0], os.Environ())
if err != nil { if err != nil {
fmt.Printf("launch command failed: %v\n", err) fmt.Printf("launch command failed: %v\n", err)
} }
} }

Loading…
Cancel
Save