Example #1
0
File: tty.go Project: hyperhq/runv
func waitPts(ctx *VmContext) {
	conn, err := utils.UnixSocketConnect(ctx.TtySockName)
	if err != nil {
		glog.Error("Cannot connect to tty socket ", err.Error())
		ctx.Hub <- &InitFailedEvent{
			Reason: "Cannot connect to tty socket " + err.Error(),
		}
		return
	}

	glog.V(1).Info("tty socket connected")

	go waitTtyMessage(ctx, conn.(*net.UnixConn))

	for {
		res, err := readTtyMessage(conn.(*net.UnixConn))
		if err != nil {
			glog.V(1).Info("tty socket closed, quit the reading goroutine ", err.Error())
			ctx.Hub <- &Interrupted{Reason: "tty socket failed " + err.Error()}
			close(ctx.ptys.channel)
			return
		}
		if len(res.Message) == 0 {
			glog.V(1).Infof("session %d closed by peer, close pty", res.Session)
			if ctx.vmHyperstartAPIVersion > 4242 {
				ctx.ptys.Close(ctx, res.Session)
			} else if ta, ok := ctx.ptys.ttys[res.Session]; ok {
				ta.closed = true
			} else {
				ctx.ptys.addEmptyPty(false, false, true, res.Session, 0)
			}
		} else if ta, ok := ctx.ptys.ttys[res.Session]; ok {
			if ta.closed {
				var code uint8 = 255
				if len(res.Message) == 1 {
					code = uint8(res.Message[0])
				}
				glog.V(1).Infof("session %d, exit code %d", res.Session, code)
				ctx.ptys.Close4242(ctx, res.Session, code)
			} else {
				for _, tty := range ta.attachments {
					if tty.Stdout != nil && res.Session == ta.stdioSeq {
						_, err := tty.Stdout.Write(res.Message)
						if err != nil {
							glog.V(1).Infof("fail to write session %d, close pty attachment", res.Session)
							ctx.ptys.Detach(ta, tty)
						}
					}
					if tty.Stderr != nil && res.Session == ta.stderrSeq {
						_, err := tty.Stderr.Write(res.Message)
						if err != nil {
							glog.V(1).Infof("fail to write session %d, close pty attachment", res.Session)
							ctx.ptys.Detach(ta, tty)
						}
					}
				}
			}
		}
	}
}
Example #2
0
func waitConsoleOutput(ctx *VmContext) {

	conn, err := utils.UnixSocketConnect(ctx.ConsoleSockName)
	if err != nil {
		glog.Error("failed to connected to ", ctx.ConsoleSockName, " ", err.Error())
		return
	}

	glog.V(1).Info("connected to ", ctx.ConsoleSockName)

	tc, err := telnet.NewConn(conn)
	if err != nil {
		glog.Error("fail to init telnet connection to ", ctx.ConsoleSockName, ": ", err.Error())
		return
	}
	glog.V(1).Infof("connected %s as telnet mode.", ctx.ConsoleSockName)

	cout := make(chan string, 128)
	go TtyLiner(tc, cout)

	for {
		line, ok := <-cout
		if ok {
			glog.V(1).Info("[console] ", line)
		} else {
			glog.Info("console output end")
			break
		}
	}
}
Example #3
0
func waitInitReady(ctx *VmContext) {
	conn, err := utils.UnixSocketConnect(ctx.HyperSockName)
	if err != nil {
		glog.Error("Cannot connect to hyper socket ", err.Error())
		ctx.Hub <- &InitFailedEvent{
			Reason: "Cannot connect to hyper socket " + err.Error(),
		}
		return
	}

	glog.Info("Wating for init messages...")

	msg, err := ReadVmMessage(conn.(*net.UnixConn))
	if err != nil {
		glog.Error("read init message failed... ", err.Error())
		ctx.Hub <- &InitFailedEvent{
			Reason: "read init message failed... " + err.Error(),
		}
		conn.Close()
	} else if msg.Code == INIT_READY {
		glog.Info("Get init ready message")
		ctx.Hub <- &InitConnectedEvent{conn: conn.(*net.UnixConn)}
		go waitCmdToInit(ctx, conn.(*net.UnixConn))
	} else {
		glog.Warningf("Get init message %d", msg.Code)
		ctx.Hub <- &InitFailedEvent{
			Reason: fmt.Sprintf("Get init message %d", msg.Code),
		}
		conn.Close()
	}
}
Example #4
0
File: runv.go Project: ZJU-SEL/runv
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
}
Example #5
0
func connectToInit(ctx *VmContext) {
	conn, err := utils.UnixSocketConnect(ctx.HyperSockName)
	if err != nil {
		glog.Error("Cannot re-connect to hyper socket ", err.Error())
		ctx.Hub <- &InitFailedEvent{
			Reason: "Cannot re-connect to hyper socket " + err.Error(),
		}
		return
	}

	go waitCmdToInit(ctx, conn.(*net.UnixConn))
}
Example #6
0
File: tty.go Project: carmark/runv
func waitPts(ctx *VmContext) {
	conn, err := utils.UnixSocketConnect(ctx.TtySockName)
	if err != nil {
		glog.Error("Cannot connect to tty socket ", err.Error())
		ctx.Hub <- &InitFailedEvent{
			Reason: "Cannot connect to tty socket " + err.Error(),
		}
		return
	}

	glog.V(1).Info("tty socket connected")

	go waitTtyMessage(ctx, conn.(*net.UnixConn))

	for {
		res, err := readTtyMessage(conn.(*net.UnixConn))
		if err != nil {
			glog.V(1).Info("tty socket closed, quit the reading goroutine ", err.Error())
			ctx.Hub <- &Interrupted{Reason: "tty socket failed " + err.Error()}
			close(ctx.ptys.channel)
			return
		}
		if ta, ok := ctx.ptys.ttys[res.session]; ok {
			if len(res.message) == 0 {
				glog.V(1).Infof("session %d closed by peer, close pty", res.session)
				ta.closed = true
			} else if ta.closed {
				var code uint8 = 255
				if len(res.message) == 1 {
					code = uint8(res.message[0])
				}
				glog.V(1).Infof("session %d, exit code", res.session, code)
				ctx.ptys.Close(ctx, res.session, code)
			} else {
				for _, tty := range ta.attachments {
					if tty.Stdout != nil && tty.liner == nil {
						_, err = tty.Stdout.Write(res.message)
					} else if tty.Stdout != nil {
						m := tty.liner.Transform(res.message)
						if len(m) > 0 {
							_, err = tty.Stdout.Write(m)
						}
					}
					if err != nil {
						glog.V(1).Infof("fail to write session %d, close pty attachment", res.session)
						ctx.ptys.Detach(ctx, res.session, tty)
					}
				}
			}
		}
	}
}
Example #7
0
func waitConsoleOutput(ctx *VmContext) {

	conn, err := utils.UnixSocketConnect(ctx.ConsoleSockName)
	if err != nil {
		glog.Error("failed to connected to ", ctx.ConsoleSockName, " ", err.Error())
		return
	}

	glog.V(1).Info("connected to ", ctx.ConsoleSockName)

	tc, err := telnet.NewConn(conn)
	if err != nil {
		glog.Error("fail to init telnet connection to ", ctx.ConsoleSockName, ": ", err.Error())
		return
	}
	glog.V(1).Infof("connected %s as telnet mode.", ctx.ConsoleSockName)

	cout := make(chan string, 128)
	go TtyLiner(tc, cout)

	const ignoreLines = 128
	for consoleLines := 0; consoleLines < ignoreLines; consoleLines++ {
		line, ok := <-cout
		if ok {
			ctx.Log(EXTRA, "[CNL] %s", line)
		} else {
			ctx.Log(INFO, "console output end")
			return
		}
	}
	if !ctx.LogLevel(EXTRA) {
		ctx.Log(DEBUG, "[CNL] omit the first %d line of console logs", ignoreLines)
	}
	for {
		line, ok := <-cout
		if ok {
			ctx.Log(DEBUG, "[CNL] %s", line)
		} else {
			ctx.Log(INFO, "console output end")
			return
		}
	}
}
Example #8
0
func waitInitReady(ctx *VmContext) {
	conn, err := utils.UnixSocketConnect(ctx.HyperSockName)
	if err != nil {
		glog.Error("Cannot connect to hyper socket ", err.Error())
		ctx.Hub <- &InitFailedEvent{
			Reason: "Cannot connect to hyper socket " + err.Error(),
		}
		return
	}

	if ctx.Boot.BootFromTemplate {
		glog.Info("boot from template")
		ctx.PauseState = PauseStatePaused
		ctx.Hub <- &InitConnectedEvent{conn: conn.(*net.UnixConn)}
		go waitCmdToInit(ctx, conn.(*net.UnixConn))
		// TODO call getVMHyperstartAPIVersion(ctx) after unpaused
		return
	}

	glog.Info("Wating for init messages...")

	msg, err := ReadVmMessage(conn.(*net.UnixConn))
	if err != nil {
		glog.Error("read init message failed... ", err.Error())
		ctx.Hub <- &InitFailedEvent{
			Reason: "read init message failed... " + err.Error(),
		}
		conn.Close()
	} else if msg.Code == hyperstartapi.INIT_READY {
		glog.Info("Get init ready message")
		ctx.Hub <- &InitConnectedEvent{conn: conn.(*net.UnixConn)}
		go waitCmdToInit(ctx, conn.(*net.UnixConn))
		if !ctx.Boot.BootToBeTemplate {
			getVMHyperstartAPIVersion(ctx)
		}
	} else {
		glog.Warningf("Get init message %d", msg.Code)
		ctx.Hub <- &InitFailedEvent{
			Reason: fmt.Sprintf("Get init message %d", msg.Code),
		}
		conn.Close()
	}
}
Example #9
0
func qmpInitializer(ctx *hypervisor.VmContext) {
	qc := qemuContext(ctx)
	conn, err := utils.UnixSocketConnect(qc.qmpSockName)
	if err != nil {
		glog.Error("failed to connected to ", qc.qmpSockName, " ", err.Error())
		qc.qmp <- qmpFail(err.Error(), nil)
		return
	}

	glog.V(1).Info("connected to ", qc.qmpSockName)

	var msg map[string]interface{}
	decoder := json.NewDecoder(conn)
	defer func() {
		if err != nil {
			conn.Close()
		}
	}()

	glog.Info("begin qmp init...")

	err = decoder.Decode(&msg)
	if err != nil {
		glog.Error("get qmp welcome failed: ", err.Error())
		qc.qmp <- qmpFail(err.Error(), nil)
		return
	}

	glog.Info("got qmp welcome, now sending command qmp_capabilities")

	cmd, err := json.Marshal(QmpCommand{Execute: "qmp_capabilities"})
	if err != nil {
		glog.Error("qmp_capabilities marshal failed ", err.Error())
		qc.qmp <- qmpFail(err.Error(), nil)
		return
	}
	_, err = conn.Write(cmd)
	if err != nil {
		glog.Error("qmp_capabilities send failed ", err.Error())
		qc.qmp <- qmpFail(err.Error(), nil)
		return
	}

	glog.Info("waiting for response")
	rsp := &QmpResponse{}
	err = decoder.Decode(rsp)
	if err != nil {
		glog.Error("response receive failed ", err.Error())
		qc.qmp <- qmpFail(err.Error(), nil)
		return
	}

	glog.Info("got for response")

	if rsp.msg.MessageType() == QMP_RESULT {
		glog.Info("QMP connection initialized")
		qc.qmp <- &QmpInit{
			conn:    conn.(*net.UnixConn),
			decoder: decoder,
		}
		return
	}

	qc.qmp <- qmpFail("handshake failed", nil)
}