mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-07-01 17:52:40 +00:00
virtcontainers: copy files form host to guest
Files are copied over gRPC and there is no limit in size of the files that can be copied. Small files are copied using just one gRPC call while big files are copied by parts. Signed-off-by: Julio Montes <julio.montes@intel.com>
This commit is contained in:
parent
dcd48a9ca1
commit
62917621c2
@ -250,4 +250,7 @@ type agent interface {
|
||||
|
||||
// setGuestDateTime asks the agent to set guest time to the provided one
|
||||
setGuestDateTime(time.Time) error
|
||||
|
||||
// copyFile copies file from host to container's rootfs
|
||||
copyFile(src, dst string) error
|
||||
}
|
||||
|
@ -1005,3 +1005,8 @@ func (h *hyper) setGuestDateTime(time.Time) error {
|
||||
// hyperstart-agent does not support setGuestDateTime
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *hyper) copyFile(src, dst string) error {
|
||||
// hyperstart-agent does not support copyFile
|
||||
return nil
|
||||
}
|
||||
|
@ -261,3 +261,11 @@ func TestHyperGetAgentUrl(t *testing.T) {
|
||||
assert.Nil(err)
|
||||
assert.Empty(url)
|
||||
}
|
||||
|
||||
func TestHyperCopyFile(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
h := &hyper{}
|
||||
|
||||
err := h.copyFile("", "")
|
||||
assert.Nil(err)
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
@ -34,6 +35,7 @@ import (
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/vishvananda/netlink"
|
||||
"golang.org/x/net/context"
|
||||
"golang.org/x/sys/unix"
|
||||
golangGrpc "google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
grpcStatus "google.golang.org/grpc/status"
|
||||
@ -63,6 +65,7 @@ var (
|
||||
shmDir = "shm"
|
||||
kataEphemeralDevType = "ephemeral"
|
||||
ephemeralPath = filepath.Join(kataGuestSandboxDir, kataEphemeralDevType)
|
||||
grpcMaxDataSize = int64(1024 * 1024)
|
||||
)
|
||||
|
||||
// KataAgentConfig is a structure storing information needed
|
||||
@ -1490,6 +1493,9 @@ func (k *kataAgent) installReqFunc(c *kataclient.AgentClient) {
|
||||
k.reqHandlers["grpc.GuestDetailsRequest"] = func(ctx context.Context, req interface{}, opts ...golangGrpc.CallOption) (interface{}, error) {
|
||||
return k.client.GetGuestDetails(ctx, req.(*grpc.GuestDetailsRequest), opts...)
|
||||
}
|
||||
k.reqHandlers["grpc.CopyFileRequest"] = func(ctx context.Context, req interface{}, opts ...golangGrpc.CallOption) (interface{}, error) {
|
||||
return k.client.CopyFile(ctx, req.(*grpc.CopyFileRequest), opts...)
|
||||
}
|
||||
k.reqHandlers["grpc.SetGuestDateTimeRequest"] = func(ctx context.Context, req interface{}, opts ...golangGrpc.CallOption) (interface{}, error) {
|
||||
return k.client.SetGuestDateTime(ctx, req.(*grpc.SetGuestDateTimeRequest), opts...)
|
||||
}
|
||||
@ -1708,3 +1714,56 @@ func (k *kataAgent) convertToRoutes(aRoutes []*aTypes.Route) (routes []*types.Ro
|
||||
|
||||
return routes
|
||||
}
|
||||
|
||||
func (k *kataAgent) copyFile(src, dst string) error {
|
||||
var st unix.Stat_t
|
||||
|
||||
err := unix.Stat(src, &st)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Could not get file %s information: %v", src, err)
|
||||
}
|
||||
|
||||
b, err := ioutil.ReadFile(src)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Could not read file %s: %v", src, err)
|
||||
}
|
||||
|
||||
fileSize := int64(len(b))
|
||||
|
||||
k.Logger().WithFields(logrus.Fields{
|
||||
"source": src,
|
||||
"dest": dst,
|
||||
}).Debugf("Copying file from host to guest")
|
||||
|
||||
cpReq := &grpc.CopyFileRequest{
|
||||
Path: dst,
|
||||
DirMode: uint32(dirMode),
|
||||
FileMode: st.Mode,
|
||||
FileSize: fileSize,
|
||||
Uid: int32(st.Uid),
|
||||
Gid: int32(st.Gid),
|
||||
}
|
||||
|
||||
// Copy file by parts if it's needed
|
||||
remainingBytes := fileSize
|
||||
offset := int64(0)
|
||||
for remainingBytes > 0 {
|
||||
bytesToCopy := int64(len(b))
|
||||
if bytesToCopy > grpcMaxDataSize {
|
||||
bytesToCopy = grpcMaxDataSize
|
||||
}
|
||||
|
||||
cpReq.Data = b[:bytesToCopy]
|
||||
cpReq.Offset = offset
|
||||
|
||||
if _, err = k.sendReq(cpReq); err != nil {
|
||||
return fmt.Errorf("Could not send CopyFile request: %v", err)
|
||||
}
|
||||
|
||||
b = b[bytesToCopy:]
|
||||
remainingBytes -= bytesToCopy
|
||||
offset += grpcMaxDataSize
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -247,6 +247,10 @@ func (p *gRPCProxy) SetGuestDateTime(ctx context.Context, req *pb.SetGuestDateTi
|
||||
return &gpb.Empty{}, nil
|
||||
}
|
||||
|
||||
func (p *gRPCProxy) CopyFile(ctx context.Context, req *pb.CopyFileRequest) (*gpb.Empty, error) {
|
||||
return &gpb.Empty{}, nil
|
||||
}
|
||||
|
||||
func gRPCRegister(s *grpc.Server, srv interface{}) {
|
||||
switch g := srv.(type) {
|
||||
case *gRPCProxy:
|
||||
@ -844,3 +848,55 @@ func TestKataGetAgentUrl(t *testing.T) {
|
||||
assert.NotEmpty(url)
|
||||
|
||||
}
|
||||
|
||||
func TestKataCopyFile(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
impl := &gRPCProxy{}
|
||||
|
||||
proxy := mock.ProxyGRPCMock{
|
||||
GRPCImplementer: impl,
|
||||
GRPCRegister: gRPCRegister,
|
||||
}
|
||||
|
||||
sockDir, err := testGenerateKataProxySockDir()
|
||||
assert.NoError(err)
|
||||
defer os.RemoveAll(sockDir)
|
||||
|
||||
testKataProxyURL := fmt.Sprintf(testKataProxyURLTempl, sockDir)
|
||||
err = proxy.Start(testKataProxyURL)
|
||||
assert.NoError(err)
|
||||
defer proxy.Stop()
|
||||
|
||||
k := &kataAgent{
|
||||
state: KataAgentState{
|
||||
URL: testKataProxyURL,
|
||||
},
|
||||
}
|
||||
|
||||
err = k.copyFile("/abc/xyz/123", "/tmp")
|
||||
assert.Error(err)
|
||||
|
||||
src, err := ioutil.TempFile("", "src")
|
||||
assert.NoError(err)
|
||||
defer os.Remove(src.Name())
|
||||
|
||||
data := []byte("abcdefghi123456789")
|
||||
_, err = src.Write(data)
|
||||
assert.NoError(err)
|
||||
assert.NoError(src.Close())
|
||||
|
||||
dst, err := ioutil.TempFile("", "dst")
|
||||
assert.NoError(err)
|
||||
assert.NoError(dst.Close())
|
||||
defer os.Remove(dst.Name())
|
||||
|
||||
orgGrpcMaxDataSize := grpcMaxDataSize
|
||||
grpcMaxDataSize = 1
|
||||
defer func() {
|
||||
grpcMaxDataSize = orgGrpcMaxDataSize
|
||||
}()
|
||||
|
||||
err = k.copyFile(src.Name(), dst.Name())
|
||||
assert.NoError(err)
|
||||
}
|
||||
|
@ -209,3 +209,8 @@ func (n *noopAgent) getGuestDetails(*grpc.GuestDetailsRequest) (*grpc.GuestDetai
|
||||
func (n *noopAgent) setGuestDateTime(time.Time) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// copyFile is the Noop agent copy file. It does nothing.
|
||||
func (n *noopAgent) copyFile(src, dst string) error {
|
||||
return nil
|
||||
}
|
||||
|
@ -272,3 +272,11 @@ func TestNoopGetAgentUrl(t *testing.T) {
|
||||
assert.Nil(err)
|
||||
assert.Empty(url)
|
||||
}
|
||||
|
||||
func TestNoopCopyFile(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
n := &noopAgent{}
|
||||
|
||||
err := n.copyFile("", "")
|
||||
assert.Nil(err)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user