refactor processing environment arguments to oz-init

networking
brl 10 years ago
parent 3bc8076a92
commit a6419afeb3

@ -2,7 +2,6 @@ package ozinit
import ( import (
"os" "os"
"github.com/codegangsta/cli"
"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"
@ -21,7 +20,12 @@ const profileDirectory = "/var/lib/oz/cells.d"
type initState struct { type initState struct {
log *logging.Logger log *logging.Logger
address string
profile *oz.Profile
uid int
gid int
user *user.User user *user.User
display int
fs *fs.Filesystem fs *fs.Filesystem
} }
@ -38,83 +42,87 @@ func createLogger() *logging.Logger {
} }
var allowRootShell = false var allowRootShell = false
var profileName = "none"
func Main() { func Main() {
app := cli.NewApp() st := parseArgs()
app.Name = "oz-init" st.runInit()
app.Action = runInit }
app.Flags = []cli.Flag {
cli.StringFlag { func parseArgs() *initState {
Name: "address", log := createLogger()
Usage: "unix socket address to listen for commands on", getvar := func(name string) string {
EnvVar: "INIT_ADDRESS", val := os.Getenv(name)
}, if val == "" {
cli.StringFlag{ log.Error("Error: missing required '%s' argument", name)
Name: "profile", os.Exit(1)
Usage: "name of profile to launch", }
EnvVar: "INIT_PROFILE", return val
}, }
cli.IntFlag{ addr := getvar("INIT_ADDRESS")
Name: "uid", pname := getvar("INIT_PROFILE")
EnvVar: "INIT_UID", uidval := getvar("INIT_UID")
}, dispval := os.Getenv("INIT_DISPLAY")
cli.IntFlag{
Name: "display", p,err := loadProfile(pname)
EnvVar: "INIT_DISPLAY", if err != nil {
}, log.Error("Could not load profile %s: %v", pname, err)
}
app.Run(os.Args)
}
func runInit(c *cli.Context) {
st := new(initState)
st.log = createLogger()
address := c.String("address")
profile := c.String("profile")
uid := uint32(c.Int("uid"))
disp := c.Int("display")
if address == "" {
st.log.Error("Error: missing required 'address' argument")
os.Exit(1) os.Exit(1)
} }
if profile == "" { uid,err := strconv.Atoi(uidval)
st.log.Error("Error: missing required 'profile' argument") if err != nil {
log.Error("Could not parse INIT_UID argument (%s) into an integer: %v", uidval, err)
os.Exit(1) os.Exit(1)
} }
profileName = profile u,err := user.LookupId(uidval)
st.log.Info("Starting oz-init for profile: %s", profile)
st.log.Info("Socket address: %s", address)
p,err := loadProfile(profile)
if err != nil { if err != nil {
st.log.Error("Could not load profile %s: %v", profile, err) log.Error("Failed to look up user with uid=%s: %v", uidval, err)
os.Exit(1) os.Exit(1)
} }
u,err := user.LookupId(strconv.FormatUint(uint64(uid), 10)) gid,err := strconv.Atoi(u.Gid)
if err != nil { if err != nil {
st.log.Error("Failed to lookup user with uid=%d: %v", uid, err) log.Error("Failed to parse gid value (%s) from user struct: %v", u.Gid, err)
os.Exit(1) os.Exit(1)
} }
st.user = u display := 0
if dispval != "" {
d,err := strconv.Atoi(dispval)
if err != nil {
log.Error("Unable to parse display (%s) into an integer: %v", dispval, err)
os.Exit(1)
}
display = d
}
return &initState{
log: log,
address: addr,
profile: p,
uid: uid,
gid: gid,
user: u,
display: display,
fs: fs.NewFromProfile(p, u, log),
}
}
fs := fs.NewFromProfile(p, u, st.log) func (st *initState) runInit() {
if err := fs.OzInit(); err != nil { st.log.Info("Starting oz-init for profile: %s", st.profile.Name)
st.log.Info("Socket address: %s", st.address)
if err := st.fs.OzInit(); err != nil {
st.log.Error("Error: setting up filesystem failed: %v\n", err) st.log.Error("Error: setting up filesystem failed: %v\n", err)
os.Exit(1) os.Exit(1)
} }
st.fs = fs if st.profile.XServer.Enabled {
if p.XServer.Enabled { if st.display == 0 {
if disp == 0 {
st.log.Error("Cannot start xpra because no display number was passed to oz-init") st.log.Error("Cannot start xpra because no display number was passed to oz-init")
os.Exit(1) os.Exit(1)
} }
st.startXpraServer(&p.XServer, fs, disp) st.startXpraServer()
} }
oz.ReapChildProcs(st.log, st.handleChildExit) oz.ReapChildProcs(st.log, st.handleChildExit)
serv := ipc.NewMsgConn(messageFactory, address) serv := ipc.NewMsgConn(messageFactory, st.address)
serv.AddHandlers( serv.AddHandlers(
handlePing, handlePing,
st.handleRunShell, st.handleRunShell,
@ -124,28 +132,28 @@ func runInit(c *cli.Context) {
st.log.Info("oz-init exiting...") st.log.Info("oz-init exiting...")
} }
func (is *initState) startXpraServer (config *oz.XServerConf, fs *fs.Filesystem, display int) { func (st *initState) startXpraServer() {
workdir := fs.Xpra() workdir := st.fs.Xpra()
if workdir == "" { if workdir == "" {
is.log.Warning("Xpra work directory not set") st.log.Warning("Xpra work directory not set")
return return
} }
logpath := path.Join(workdir, "xpra-server.out") logpath := path.Join(workdir, "xpra-server.out")
f,err := os.Create(logpath) f,err := os.Create(logpath)
if err != nil { if err != nil {
is.log.Warning("Failed to open xpra logfile (%s): %v", logpath, err) st.log.Warning("Failed to open xpra logfile (%s): %v", logpath, err)
return return
} }
defer f.Close() defer f.Close()
xpra := xpra.NewServer(config, uint64(display), workdir) xpra := xpra.NewServer(&st.profile.XServer, uint64(st.display), workdir)
xpra.Process.Stdout = f xpra.Process.Stdout = f
xpra.Process.Stderr = f xpra.Process.Stderr = f
xpra.Process.Env = []string{ xpra.Process.Env = []string{
"HOME="+ is.user.HomeDir, "HOME="+ st.user.HomeDir,
} }
is.log.Info("Starting xpra server") st.log.Info("Starting xpra server")
if err := xpra.Process.Start(); err != nil { if err := xpra.Process.Start(); err != nil {
is.log.Warning("Failed to start xpra server: %v", err) st.log.Warning("Failed to start xpra server: %v", err)
} }
} }
@ -166,14 +174,14 @@ func handlePing(ping *PingMsg, msg *ipc.Message) error {
return msg.Respond(&PingMsg{Data: ping.Data}) return msg.Respond(&PingMsg{Data: ping.Data})
} }
func (is *initState) handleRunShell(rs *RunShellMsg, msg *ipc.Message) error { func (st *initState) handleRunShell(rs *RunShellMsg, msg *ipc.Message) error {
if msg.Ucred == nil { if msg.Ucred == nil {
return msg.Respond(&ErrorMsg{"No credentials received for RunShell command"}) return msg.Respond(&ErrorMsg{"No credentials received for RunShell command"})
} }
if msg.Ucred.Uid == 0 || msg.Ucred.Gid == 0 && !allowRootShell { if msg.Ucred.Uid == 0 || msg.Ucred.Gid == 0 && !allowRootShell {
return msg.Respond(&ErrorMsg{"Cannot open shell because allowRootShell is disabled"}) return msg.Respond(&ErrorMsg{"Cannot open shell because allowRootShell is disabled"})
} }
is.log.Info("Starting shell with uid = %d, gid = %d", msg.Ucred.Uid, msg.Ucred.Gid) st.log.Info("Starting shell with uid = %d, gid = %d", msg.Ucred.Uid, msg.Ucred.Gid)
cmd := exec.Command("/bin/sh", "-i") cmd := exec.Command("/bin/sh", "-i")
cmd.SysProcAttr = &syscall.SysProcAttr{} cmd.SysProcAttr = &syscall.SysProcAttr{}
cmd.SysProcAttr.Credential = &syscall.Credential{ cmd.SysProcAttr.Credential = &syscall.Credential{
@ -184,8 +192,8 @@ func (is *initState) handleRunShell(rs *RunShellMsg, msg *ipc.Message) error {
cmd.Env = append(cmd.Env, "TERM="+rs.Term) cmd.Env = append(cmd.Env, "TERM="+rs.Term)
} }
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] $ ", profileName)) cmd.Env = append(cmd.Env, fmt.Sprintf("PS1=[%s] $ ", st.profile.Name))
is.log.Info("Executing shell...") st.log.Info("Executing shell...")
f,err := ptyStart(cmd) f,err := ptyStart(cmd)
defer f.Close() defer f.Close()
if err != nil { if err != nil {

Loading…
Cancel
Save