Example #1
0
File: runv.go Project: ZJU-SEL/runv
func runvGetTag(conn net.Conn) (tag string, err error) {
	msg, err := hypervisor.ReadVmMessage(conn.(*net.UnixConn))
	if err != nil {
		fmt.Printf("read runv server data failed: %v\n", err)
		return "", err
	}

	if msg.Code != RUNV_ACK {
		return "", fmt.Errorf("unexpected respond code")
	}

	return string(msg.Message), nil
}
Example #2
0
File: tty.go Project: ZJU-SEL/runv
// stdin/stdout <-> conn
func containerTtySplice(root, container string, conn net.Conn, isContainer bool) (int, error) {
	tag, err := runvGetTag(conn)
	if err != nil {
		return -1, err
	}
	fmt.Printf("tag=%s\n", tag)

	outFd, isTerminalOut := term.GetFdInfo(os.Stdout)
	newTty(root, container, tag, outFd, isTerminalOut).monitorTtySize()
	_, err = term.TtySplice(conn)
	if err != nil {
		return -1, err
	}

	cmd := &ttyTagCmd{Root: root, Container: "", Tag: tag}
	if isContainer {
		cmd.Container = container
	}
	conn, err = runvRequest(root, container, RUNV_EXITSTATUS, cmd)
	if err != nil {
		fmt.Printf("runvRequest failed: %v\n", err)
		return -1, err
	}
	defer conn.Close()

	msg, err := hypervisor.ReadVmMessage(conn.(*net.UnixConn))
	if err != nil {
		fmt.Printf("read runv server data failed: %v\n", err)
		return -1, err
	}

	if msg.Code != RUNV_EXITSTATUS {
		return -1, fmt.Errorf("unexpected respond code")
	}

	return int(msg.Message[0]), nil
}
Example #3
0
File: runv.go Project: ZJU-SEL/runv
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")
	}
}
Example #4
0
File: runv.go Project: ZJU-SEL/runv
func startVContainer(context *nsContext, root, container string) {
	stateDir := filepath.Join(root, container)

	err := createVSocket(context, root, container)
	if err != nil {
		fmt.Printf("create runv Socket err: %v\n", err)
		return
	}

	sock, ok := context.sockets[container]
	if !ok {
		fmt.Printf("can not find runv Socket, container %v\n", container)
		return
	}

	conn, err := sock.Accept()
	if err != nil {
		fmt.Printf("accept on runv Socket err: %v\n", err)
		return
	}

	// get config from sock
	msg, err := hypervisor.ReadVmMessage(conn.(*net.UnixConn))
	if err != nil || msg.Code != RUNV_STARTCONTAINER {
		fmt.Printf("read runv client data failed: %v\n", err)
		return
	}
	config := &startConfig{}
	err = json.Unmarshal(msg.Message, config)
	if err != nil || config.Root != root || config.Name != container {
		fmt.Printf("parse runv start config failed: %v\n", err)
		return
	}

	// start pure pod
	err = startRunvPod(context, config)
	if err != nil {
		fmt.Printf("Start Pod failed: %s\n", err.Error())
		return
	}
	defer cleanupRunvPod(context, container)

	// save the state
	state := &specs.State{
		Version:    config.LinuxSpec.Spec.Version,
		ID:         container,
		Pid:        -1,
		BundlePath: config.BundlePath,
	}
	stateData, err := json.MarshalIndent(state, "", "\t")
	if err != nil {
		fmt.Printf("%s\n", err.Error())
		return
	}
	stateFile := filepath.Join(stateDir, "state.json")
	err = ioutil.WriteFile(stateFile, stateData, 0644)
	if err != nil {
		fmt.Printf("%s\n", err.Error())
		return
	}

	userContainer := pod.ConvertOCF2UserContainer(&config.LinuxSpec, &config.LinuxRuntimeSpec)
	info, err := prepareInfo(config, userContainer, context.vmId)
	if err != nil {
		fmt.Printf("%s\n", err.Error())
		return
	}

	defer func() {
		rootDir := filepath.Join(hypervisor.BaseDir, context.vmId, hypervisor.ShareDirTag, info.Id, "rootfs")
		utils.Umount(rootDir)
		os.RemoveAll(filepath.Join(hypervisor.BaseDir, context.vmId, hypervisor.ShareDirTag, info.Id))
	}()

	tag, _ := runvAllocAndRespondTag(conn)

	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.Attach(tty, info.Id, nil)
	if err != nil {
		fmt.Printf("StartPod fail: fail to set up tty connection.\n")
		return
	}

	err = execPrestartHooks(&config.LinuxRuntimeSpec.RuntimeSpec, state)
	if err != nil {
		fmt.Printf("execute Prestart hooks failed, %s\n", err.Error())
		return
	}

	context.podStatus.AddContainer(info.Id, context.podId, "", []string{}, types.S_POD_CREATED)
	context.vm.NewContainer(userContainer, info)
	ListenAndHandleRunvRequests(context, info, sock)

	err = execPoststartHooks(&config.LinuxRuntimeSpec.RuntimeSpec, state)
	if err != nil {
		fmt.Printf("execute Poststart hooks failed %s\n", err.Error())
	}

	err = tty.WaitForFinish()
	if err != nil {
		fmt.Printf("get exit code failed %s\n", err.Error())
	}

	err = execPoststopHooks(&config.LinuxRuntimeSpec.RuntimeSpec, state)
	if err != nil {
		fmt.Printf("execute Poststop hooks failed %s\n", err.Error())
		return
	}
}