Example #1
0
func (s *rpcServer) Enter(inStream pb.Kurma_EnterServer) error {
	s.log.Debug("Received enter request")

	// read the first chunk to make sure its real and get the container ID
	chunk, err := inStream.Recv()
	if err != nil {
		return err
	}

	// create the outbound stream
	outStream, err := s.client.Enter(inStream.Context())
	if err != nil {
		return err
	}

	// Create our inbound streams
	inWriter := pb.NewByteStreamWriter(inStream, chunk.StreamId)
	inReader := pb.NewByteStreamReader(inStream, nil)

	// Create our outbound streams
	outWriter := pb.NewByteStreamWriter(outStream, chunk.StreamId)
	outReader := pb.NewByteStreamReader(outStream, nil)

	// write the first byte to the backend so it is initialized
	if _, err := outWriter.Write(nil); err != nil {
		return err
	}

	// stream between!
	go io.Copy(outWriter, inReader)
	io.Copy(inWriter, outReader)
	outStream.CloseSend()
	return nil
}
Example #2
0
func enter(cmd *cli.Cmd) error {
	// Set the local terminal in raw mode to turn off buffering and local
	// echo. Also defers setting it back to normal for when the call is done.
	termios, err := raw.MakeRaw(os.Stdin.Fd())
	if err != nil {
		return err
	}
	defer raw.TcSetAttr(os.Stdin.Fd(), termios)

	// Initialize the call and send the first packet so that it knows what
	// container we're connecting to.
	stream, err := cmd.Client.Enter(context.Background())
	if err != nil {
		return err
	}
	w := pb.NewByteStreamWriter(stream, cmd.Args[0])
	r := pb.NewByteStreamReader(stream, nil)
	if _, err := w.Write(nil); err != nil {
		return err
	}

	go io.Copy(w, os.Stdin)
	io.Copy(os.Stdout, r)
	stream.CloseSend()
	return nil
}
Example #3
0
func create(cmd *cli.Cmd) error {
	// open the file
	f, err := os.Open(cmd.Args[0])
	if err != nil {
		return err
	}
	defer f.Close()

	// find the manifest file, then rewind
	manifest, err := findManifest(f)
	if err != nil {
		return err
	}
	if _, err := f.Seek(0, 0); err != nil {
		return err
	}

	req := &pb.CreateRequest{
		Manifest: manifest,
	}

	// trigger container creation then upload the ACI image
	resp, err := cmd.Client.Create(context.Background(), req)
	if err != nil {
		return err
	}
	stream, err := cmd.Client.UploadImage(context.Background())
	if err != nil {
		return err
	}

	w := pb.NewByteStreamWriter(stream, resp.ImageUploadId)
	if _, err := io.Copy(w, f); err != nil {
		return fmt.Errorf("write error: %v", err)
	}
	if _, err := stream.CloseAndRecv(); err != nil {
		return err
	}

	// fmt.Printf("Launched container %s\n", resp.Uuid)
	return nil
}
Example #4
0
func (s *rpcServer) Enter(stream pb.Kurma_EnterServer) error {
	s.log.Debug("Received enter request")

	// Receive the first chunk so we can get the stream ID, which will be the UUID
	// of the container. The byte portion will be blank, the client always sends a
	// chunk first so the UUID is available immediately.
	chunk, err := stream.Recv()
	if err != nil {
		return err
	}

	// get the container
	container := s.manager.Container(chunk.StreamId)
	if container == nil {
		return fmt.Errorf("specified container not found")
	}

	// configure the io.Reader/Writer for the transport
	w := pb.NewByteStreamWriter(stream, chunk.StreamId)
	r := pb.NewByteStreamReader(stream, nil)

	// create a pty, which we'll use for the process entering the container and
	// copy the data back up the transport.
	master, slave, err := pty.Open()
	if err != nil {
		return err
	}
	defer func() {
		slave.Close()
		master.Close()
	}()
	go io.Copy(w, master)
	go io.Copy(master, r)

	// enter into the container
	if err := container.Enter(slave); err != nil {
		return err
	}
	s.log.Debugf("Enter request finished")
	return nil
}
Example #5
0
func (s *rpcServer) UploadImage(inStream pb.Kurma_UploadImageServer) error {
	s.log.Debug("Received upload request")

	// NOTE: Unlike in the local daemon, we don't need to revalidate the image
	// manifest between Create and Upload. The backend validates in the Manager
	// because within the backend, there are multiple inputs to Manager.Create
	// (ie, bootstrapping vs the local API).
	//
	// Over the local API, it will cache the image manifest from the Create call
	// and re-use it on the UploadImage call, not pulling it from the binary
	// image.

	packet, err := inStream.Recv()
	if err != nil {
		return err
	}

	outStream, err := s.client.UploadImage(inStream.Context())
	if err != nil {
		return err
	}

	r := pb.NewByteStreamReader(inStream, packet)
	w := pb.NewByteStreamWriter(outStream, packet.StreamId)

	if _, err := io.Copy(w, r); err != nil {
		return fmt.Errorf("write error: %v", err)
	}
	if _, err := outStream.CloseAndRecv(); err != nil {
		return err
	}
	if err := inStream.SendAndClose(&pb.None{}); err != nil {
		return err
	}
	return nil
}