func runvRequest(root, name string, code uint32, msg interface{}) (net.Conn, error) { conn, err := utils.UnixSocketConnect(filepath.Join(root, name, "runv.sock")) if err != nil { return nil, err } cmd, err := json.Marshal(msg) if err != nil { conn.Close() return nil, err } m := &hypervisor.DecodedMessage{ Code: code, Message: cmd, } data := hypervisor.NewVmMessage(m) w, err := conn.Write(data[:]) if w != len(data) { err = fmt.Errorf("Not full write") // TODO } if err != nil { conn.Close() return nil, err } return conn, nil }
func runvAllocAndRespondTag(conn net.Conn) (tag string, err error) { tag = pod.RandStr(8, "alphanum") m := &hypervisor.DecodedMessage{ Code: RUNV_ACK, Message: []byte(tag), } data := hypervisor.NewVmMessage(m) conn.Write(data) return tag, nil }
func HandleRunvRequest(context *nsContext, info *hypervisor.ContainerInfo, conn net.Conn) { defer context.wg.Done() defer conn.Close() msg, err := hypervisor.ReadVmMessage(conn.(*net.UnixConn)) if err != nil { fmt.Printf("read runv client data failed: %v\n", err) return } switch msg.Code { case RUNV_INITCONTAINER: { initCmd := &initContainerCmd{} err = json.Unmarshal(msg.Message, initCmd) if err != nil { fmt.Printf("parse runv init container command failed: %v\n", err) return } startVContainer(context, initCmd.Root, initCmd.Name) } case RUNV_EXECCMD: { tag, _ := runvAllocAndRespondTag(conn) fmt.Printf("client exec cmd request %s\n", msg.Message[:]) tty := &hypervisor.TtyIO{ ClientTag: tag, Stdin: conn, Stdout: conn, Callback: make(chan *types.VmResponse, 1), } context.Lock() context.ttyList[tag] = tty context.Unlock() err = context.vm.Exec(tty, info.Id, string(msg.Message[:])) if err != nil { fmt.Printf("read runv client data failed: %v\n", err) } } case RUNV_EXITSTATUS: { var code uint8 = 255 tagCmd := &ttyTagCmd{} err = json.Unmarshal(msg.Message, &tagCmd) if err != nil { fmt.Printf("parse exit status failed: %v\n", err) return } fmt.Printf("client get exit status: tag %v\n", tagCmd) context.Lock() if tty, ok := context.ttyList[tagCmd.Tag]; ok { code = uint8(tty.ExitCode) delete(context.ttyList, tagCmd.Tag) } context.Unlock() m := &hypervisor.DecodedMessage{ Code: RUNV_EXITSTATUS, Message: []byte{code}, } data := hypervisor.NewVmMessage(m) conn.Write(data) /* Get exit code of Container, it's time to let container go */ if tagCmd.Container != "" { cleanupVSocket(context, tagCmd.Root, tagCmd.Container) } } case RUNV_WINSIZE: { var winSize ttyWinSize json.Unmarshal(msg.Message, &winSize) //fmt.Printf("client exec winsize request %v\n", winSize) context.vm.Tty(winSize.Tag, winSize.Height, winSize.Width) } case RUNV_KILLCONTAINER: { killCmd := &killContainerCmd{} err = json.Unmarshal(msg.Message, killCmd) if err != nil { fmt.Printf("parse runv kill container command failed: %v\n", err) return } context.vm.KillContainer(info.Id, killCmd.Signal) } default: fmt.Printf("unknown cient request\n") } }