now you can kill sandboxes

master
brl 10 years ago
parent 1a6d5ff18d
commit 2b2de2fa31

@ -98,6 +98,21 @@ func Clean(arg string) error {
} }
} }
func KillSandbox(id int) error {
resp, err := clientSend(&KillSandboxMsg{Id: id})
if err != nil {
return err
}
switch body := resp.Body.(type) {
case *ErrorMsg:
return errors.New(body.Msg)
case *OkMsg:
return nil
default:
return fmt.Errorf("Unexpected message received %+v", body)
}
}
func parseProfileArg(arg string) (int, string, error) { func parseProfileArg(arg string) (int, string, error) {
if len(arg) == 0 { if len(arg) == 0 {
return 0, "", errors.New("profile argument needed") return 0, "", errors.New("profile argument needed")

@ -11,6 +11,7 @@ import (
"github.com/subgraph/oz/network" "github.com/subgraph/oz/network"
"github.com/op/go-logging" "github.com/op/go-logging"
"os"
) )
type daemonState struct { type daemonState struct {
@ -35,6 +36,7 @@ func Main() {
d.handleLaunch, d.handleLaunch,
d.handleListSandboxes, d.handleListSandboxes,
d.handleClean, d.handleClean,
d.handleKillSandbox,
d.handleLogs, d.handleLogs,
) )
if err != nil { if err != nil {
@ -133,6 +135,26 @@ func (d *daemonState) handleLaunch(msg *LaunchMsg, m *ipc.Message) error {
return m.Respond(&OkMsg{}) return m.Respond(&OkMsg{})
} }
func (d *daemonState) handleKillSandbox(msg *KillSandboxMsg, m *ipc.Message) error {
sbox := d.sandboxById(msg.Id)
if sbox == nil {
return m.Respond(&ErrorMsg{fmt.Sprintf("no sandbox found with id = %d", msg.Id)})
}
if err := sbox.init.Process.Signal(os.Interrupt); err != nil {
return m.Respond(&ErrorMsg{fmt.Sprintf("failed to send interrupt signal: %v", err)})
}
return m.Respond(&OkMsg{})
}
func (d *daemonState) sandboxById(id int) *Sandbox {
for _, sb := range d.sandboxes {
if sb.id == id {
return sb
}
}
return nil
}
func (d *daemonState) getProfileByIdxOrName(index int, name string) (*oz.Profile, error) { func (d *daemonState) getProfileByIdxOrName(index int, name string) (*oz.Profile, error) {
if len(name) == 0 { if len(name) == 0 {
if index < 1 || index > len(d.profiles) { if index < 1 || index > len(d.profiles) {

@ -50,6 +50,10 @@ type ListSandboxesResp struct {
Sandboxes []SandboxInfo "ListSandboxesResp" Sandboxes []SandboxInfo "ListSandboxesResp"
} }
type KillSandboxMsg struct {
Id int "KillSandbox"
}
type CleanMsg struct { type CleanMsg struct {
Index int "Clean" Index int "Clean"
Name string Name string
@ -73,6 +77,7 @@ var messageFactory = ipc.NewMsgFactory(
new(LaunchMsg), new(LaunchMsg),
new(ListSandboxesMsg), new(ListSandboxesMsg),
new(ListSandboxesResp), new(ListSandboxesResp),
new(KillSandboxMsg),
new(CleanMsg), new(CleanMsg),
new(LogsMsg), new(LogsMsg),
new(LogData), new(LogData),

@ -21,6 +21,7 @@ import (
"github.com/kr/pty" "github.com/kr/pty"
"github.com/op/go-logging" "github.com/op/go-logging"
"os/signal"
) )
const SocketAddress = "/tmp/oz-init-control" const SocketAddress = "/tmp/oz-init-control"
@ -151,6 +152,8 @@ func parseArgs() *initState {
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)
sigs := make(chan os.Signal)
signal.Notify(sigs, syscall.SIGTERM, os.Interrupt)
if st.profile.Networking.Nettype != "host" { if st.profile.Networking.Nettype != "host" {
err := network.NetSetup(st.network) err := network.NetSetup(st.network)
@ -192,6 +195,8 @@ func (st *initState) runInit() {
} }
os.Stderr.WriteString("OK\n") os.Stderr.WriteString("OK\n")
go st.processSignals(sigs, s)
if err := s.Run(); err != nil { if err := s.Run(); err != nil {
st.log.Warning("MsgServer.Run() return err: %v", err) st.log.Warning("MsgServer.Run() return err: %v", err)
} }
@ -247,7 +252,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)
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)
@ -361,3 +366,11 @@ func ptyStart(c *exec.Cmd) (ptty *os.File, err error) {
func (is *initState) handleChildExit(pid int, wstatus syscall.WaitStatus) { func (is *initState) handleChildExit(pid int, wstatus syscall.WaitStatus) {
is.log.Debug("Child process pid=%d exited with status %d", pid, wstatus.ExitStatus()) is.log.Debug("Child process pid=%d exited with status %d", pid, wstatus.ExitStatus())
} }
func (st *initState) processSignals(c <-chan os.Signal, s *ipc.MsgServer) {
for {
sig := <-c
st.log.Info("Recieved signal (%v)", sig)
s.Close()
}
}

@ -42,6 +42,10 @@ func main() {
Name: "clean", Name: "clean",
Action: handleClean, Action: handleClean,
}, },
{
Name: "kill",
Action: handleKill,
},
{ {
Name: "logs", Name: "logs",
Action: handleLogs, Action: handleLogs,
@ -153,6 +157,21 @@ func handleClean(c *cli.Context) {
} }
} }
func handleKill(c *cli.Context) {
if len(c.Args()) == 0 {
fmt.Println("Need a sandbox id to kill\n")
os.Exit(1)
}
id, err := strconv.Atoi(c.Args()[0])
if err != nil {
fmt.Printf("Could not parse id value %s\n", c.Args()[0])
os.Exit(1)
}
if err := daemon.KillSandbox(id); err != nil {
fmt.Println("Kill command failed:", err)
}
}
func handleLogs(c *cli.Context) { func handleLogs(c *cli.Context) {
follow := c.Bool("f") follow := c.Bool("f")
ch, err := daemon.Logs(0, follow) ch, err := daemon.Logs(0, follow)

Loading…
Cancel
Save