Merge pull request #1041 from devimc/topic/no9pCopyFiles

Copy files from host to guest
This commit is contained in:
Eric Ernst 2018-12-19 12:16:34 -08:00 committed by GitHub
commit b51c57e6fe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 829 additions and 189 deletions

4
Gopkg.lock generated
View File

@ -245,7 +245,7 @@
revision = "737f03de595e216116264cc74a58e5f2a1df789a" revision = "737f03de595e216116264cc74a58e5f2a1df789a"
[[projects]] [[projects]]
digest = "1:bc6ec5ed69614cb8304b6b6532a4df381ebf5a57c4fc065cd593f54e9ff7e7a7" digest = "1:590bfb6f8d5741fa38bb3022f55588fb7e06389f6b7b6692a965e0e5a4363fb1"
name = "github.com/kata-containers/agent" name = "github.com/kata-containers/agent"
packages = [ packages = [
"pkg/types", "pkg/types",
@ -253,7 +253,7 @@
"protocols/grpc", "protocols/grpc",
] ]
pruneopts = "NUT" pruneopts = "NUT"
revision = "100dbc569d0673744cc66accfbb61a0229c5b0ad" revision = "8e48125fa2a793706e5e660e95bdc9755f1cf474"
[[projects]] [[projects]]
digest = "1:04054595e5c5a35d1553a7f3464d18577caf597445d643992998643df56d4afd" digest = "1:04054595e5c5a35d1553a7f3464d18577caf597445d643992998643df56d4afd"

View File

@ -56,7 +56,7 @@
[[constraint]] [[constraint]]
name = "github.com/kata-containers/agent" name = "github.com/kata-containers/agent"
revision = "100dbc569d0673744cc66accfbb61a0229c5b0ad" revision = "8e48125fa2a793706e5e660e95bdc9755f1cf474"
[[constraint]] [[constraint]]
name = "github.com/containerd/cri-containerd" name = "github.com/containerd/cri-containerd"

View File

@ -59,6 +59,7 @@
Storage Storage
Device Device
StringUser StringUser
CopyFileRequest
CheckRequest CheckRequest
HealthCheckResponse HealthCheckResponse
VersionCheckResponse VersionCheckResponse
@ -1602,6 +1603,89 @@ func (m *StringUser) GetAdditionalGids() []string {
return nil return nil
} }
type CopyFileRequest struct {
// Path is the destination file in the guest. It must be absolute,
// canonical and below /run.
Path string `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"`
// FileSize is the expected file size, for security reasons write operations
// are made in a temporary file, once it has the expected size, it's moved
// to the destination path.
FileSize int64 `protobuf:"varint,2,opt,name=file_size,json=fileSize,proto3" json:"file_size,omitempty"`
// FileMode is the file mode.
FileMode uint32 `protobuf:"varint,3,opt,name=file_mode,json=fileMode,proto3" json:"file_mode,omitempty"`
// DirMode is the mode for the parent directories of destination path.
DirMode uint32 `protobuf:"varint,4,opt,name=dir_mode,json=dirMode,proto3" json:"dir_mode,omitempty"`
// Uid is the numeric user id.
Uid int32 `protobuf:"varint,5,opt,name=uid,proto3" json:"uid,omitempty"`
// Gid is the numeric group id.
Gid int32 `protobuf:"varint,6,opt,name=gid,proto3" json:"gid,omitempty"`
// Offset for the next write operation.
Offset int64 `protobuf:"varint,7,opt,name=offset,proto3" json:"offset,omitempty"`
// Data to write in the destination file.
Data []byte `protobuf:"bytes,8,opt,name=data,proto3" json:"data,omitempty"`
}
func (m *CopyFileRequest) Reset() { *m = CopyFileRequest{} }
func (m *CopyFileRequest) String() string { return proto.CompactTextString(m) }
func (*CopyFileRequest) ProtoMessage() {}
func (*CopyFileRequest) Descriptor() ([]byte, []int) { return fileDescriptorAgent, []int{49} }
func (m *CopyFileRequest) GetPath() string {
if m != nil {
return m.Path
}
return ""
}
func (m *CopyFileRequest) GetFileSize() int64 {
if m != nil {
return m.FileSize
}
return 0
}
func (m *CopyFileRequest) GetFileMode() uint32 {
if m != nil {
return m.FileMode
}
return 0
}
func (m *CopyFileRequest) GetDirMode() uint32 {
if m != nil {
return m.DirMode
}
return 0
}
func (m *CopyFileRequest) GetUid() int32 {
if m != nil {
return m.Uid
}
return 0
}
func (m *CopyFileRequest) GetGid() int32 {
if m != nil {
return m.Gid
}
return 0
}
func (m *CopyFileRequest) GetOffset() int64 {
if m != nil {
return m.Offset
}
return 0
}
func (m *CopyFileRequest) GetData() []byte {
if m != nil {
return m.Data
}
return nil
}
func init() { func init() {
proto.RegisterType((*CreateContainerRequest)(nil), "grpc.CreateContainerRequest") proto.RegisterType((*CreateContainerRequest)(nil), "grpc.CreateContainerRequest")
proto.RegisterType((*StartContainerRequest)(nil), "grpc.StartContainerRequest") proto.RegisterType((*StartContainerRequest)(nil), "grpc.StartContainerRequest")
@ -1652,6 +1736,7 @@ func init() {
proto.RegisterType((*Storage)(nil), "grpc.Storage") proto.RegisterType((*Storage)(nil), "grpc.Storage")
proto.RegisterType((*Device)(nil), "grpc.Device") proto.RegisterType((*Device)(nil), "grpc.Device")
proto.RegisterType((*StringUser)(nil), "grpc.StringUser") proto.RegisterType((*StringUser)(nil), "grpc.StringUser")
proto.RegisterType((*CopyFileRequest)(nil), "grpc.CopyFileRequest")
} }
// Reference imports to suppress errors if they are not otherwise used. // Reference imports to suppress errors if they are not otherwise used.
@ -1703,6 +1788,7 @@ type AgentServiceClient interface {
ReseedRandomDev(ctx context.Context, in *ReseedRandomDevRequest, opts ...grpc1.CallOption) (*google_protobuf2.Empty, error) ReseedRandomDev(ctx context.Context, in *ReseedRandomDevRequest, opts ...grpc1.CallOption) (*google_protobuf2.Empty, error)
GetGuestDetails(ctx context.Context, in *GuestDetailsRequest, opts ...grpc1.CallOption) (*GuestDetailsResponse, error) GetGuestDetails(ctx context.Context, in *GuestDetailsRequest, opts ...grpc1.CallOption) (*GuestDetailsResponse, error)
SetGuestDateTime(ctx context.Context, in *SetGuestDateTimeRequest, opts ...grpc1.CallOption) (*google_protobuf2.Empty, error) SetGuestDateTime(ctx context.Context, in *SetGuestDateTimeRequest, opts ...grpc1.CallOption) (*google_protobuf2.Empty, error)
CopyFile(ctx context.Context, in *CopyFileRequest, opts ...grpc1.CallOption) (*google_protobuf2.Empty, error)
} }
type agentServiceClient struct { type agentServiceClient struct {
@ -1965,6 +2051,15 @@ func (c *agentServiceClient) SetGuestDateTime(ctx context.Context, in *SetGuestD
return out, nil return out, nil
} }
func (c *agentServiceClient) CopyFile(ctx context.Context, in *CopyFileRequest, opts ...grpc1.CallOption) (*google_protobuf2.Empty, error) {
out := new(google_protobuf2.Empty)
err := grpc1.Invoke(ctx, "/grpc.AgentService/CopyFile", in, out, c.cc, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// Server API for AgentService service // Server API for AgentService service
type AgentServiceServer interface { type AgentServiceServer interface {
@ -2006,6 +2101,7 @@ type AgentServiceServer interface {
ReseedRandomDev(context.Context, *ReseedRandomDevRequest) (*google_protobuf2.Empty, error) ReseedRandomDev(context.Context, *ReseedRandomDevRequest) (*google_protobuf2.Empty, error)
GetGuestDetails(context.Context, *GuestDetailsRequest) (*GuestDetailsResponse, error) GetGuestDetails(context.Context, *GuestDetailsRequest) (*GuestDetailsResponse, error)
SetGuestDateTime(context.Context, *SetGuestDateTimeRequest) (*google_protobuf2.Empty, error) SetGuestDateTime(context.Context, *SetGuestDateTimeRequest) (*google_protobuf2.Empty, error)
CopyFile(context.Context, *CopyFileRequest) (*google_protobuf2.Empty, error)
} }
func RegisterAgentServiceServer(s *grpc1.Server, srv AgentServiceServer) { func RegisterAgentServiceServer(s *grpc1.Server, srv AgentServiceServer) {
@ -2516,6 +2612,24 @@ func _AgentService_SetGuestDateTime_Handler(srv interface{}, ctx context.Context
return interceptor(ctx, in, info, handler) return interceptor(ctx, in, info, handler)
} }
func _AgentService_CopyFile_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc1.UnaryServerInterceptor) (interface{}, error) {
in := new(CopyFileRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AgentServiceServer).CopyFile(ctx, in)
}
info := &grpc1.UnaryServerInfo{
Server: srv,
FullMethod: "/grpc.AgentService/CopyFile",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AgentServiceServer).CopyFile(ctx, req.(*CopyFileRequest))
}
return interceptor(ctx, in, info, handler)
}
var _AgentService_serviceDesc = grpc1.ServiceDesc{ var _AgentService_serviceDesc = grpc1.ServiceDesc{
ServiceName: "grpc.AgentService", ServiceName: "grpc.AgentService",
HandlerType: (*AgentServiceServer)(nil), HandlerType: (*AgentServiceServer)(nil),
@ -2632,6 +2746,10 @@ var _AgentService_serviceDesc = grpc1.ServiceDesc{
MethodName: "SetGuestDateTime", MethodName: "SetGuestDateTime",
Handler: _AgentService_SetGuestDateTime_Handler, Handler: _AgentService_SetGuestDateTime_Handler,
}, },
{
MethodName: "CopyFile",
Handler: _AgentService_CopyFile_Handler,
},
}, },
Streams: []grpc1.StreamDesc{}, Streams: []grpc1.StreamDesc{},
Metadata: "agent.proto", Metadata: "agent.proto",
@ -4544,6 +4662,66 @@ func (m *StringUser) MarshalTo(dAtA []byte) (int, error) {
return i, nil return i, nil
} }
func (m *CopyFileRequest) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalTo(dAtA)
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *CopyFileRequest) MarshalTo(dAtA []byte) (int, error) {
var i int
_ = i
var l int
_ = l
if len(m.Path) > 0 {
dAtA[i] = 0xa
i++
i = encodeVarintAgent(dAtA, i, uint64(len(m.Path)))
i += copy(dAtA[i:], m.Path)
}
if m.FileSize != 0 {
dAtA[i] = 0x10
i++
i = encodeVarintAgent(dAtA, i, uint64(m.FileSize))
}
if m.FileMode != 0 {
dAtA[i] = 0x18
i++
i = encodeVarintAgent(dAtA, i, uint64(m.FileMode))
}
if m.DirMode != 0 {
dAtA[i] = 0x20
i++
i = encodeVarintAgent(dAtA, i, uint64(m.DirMode))
}
if m.Uid != 0 {
dAtA[i] = 0x28
i++
i = encodeVarintAgent(dAtA, i, uint64(m.Uid))
}
if m.Gid != 0 {
dAtA[i] = 0x30
i++
i = encodeVarintAgent(dAtA, i, uint64(m.Gid))
}
if m.Offset != 0 {
dAtA[i] = 0x38
i++
i = encodeVarintAgent(dAtA, i, uint64(m.Offset))
}
if len(m.Data) > 0 {
dAtA[i] = 0x42
i++
i = encodeVarintAgent(dAtA, i, uint64(len(m.Data)))
i += copy(dAtA[i:], m.Data)
}
return i, nil
}
func encodeVarintAgent(dAtA []byte, offset int, v uint64) int { func encodeVarintAgent(dAtA []byte, offset int, v uint64) int {
for v >= 1<<7 { for v >= 1<<7 {
dAtA[offset] = uint8(v&0x7f | 0x80) dAtA[offset] = uint8(v&0x7f | 0x80)
@ -5367,6 +5545,38 @@ func (m *StringUser) Size() (n int) {
return n return n
} }
func (m *CopyFileRequest) Size() (n int) {
var l int
_ = l
l = len(m.Path)
if l > 0 {
n += 1 + l + sovAgent(uint64(l))
}
if m.FileSize != 0 {
n += 1 + sovAgent(uint64(m.FileSize))
}
if m.FileMode != 0 {
n += 1 + sovAgent(uint64(m.FileMode))
}
if m.DirMode != 0 {
n += 1 + sovAgent(uint64(m.DirMode))
}
if m.Uid != 0 {
n += 1 + sovAgent(uint64(m.Uid))
}
if m.Gid != 0 {
n += 1 + sovAgent(uint64(m.Gid))
}
if m.Offset != 0 {
n += 1 + sovAgent(uint64(m.Offset))
}
l = len(m.Data)
if l > 0 {
n += 1 + l + sovAgent(uint64(l))
}
return n
}
func sovAgent(x uint64) (n int) { func sovAgent(x uint64) (n int) {
for { for {
n++ n++
@ -11402,6 +11612,230 @@ func (m *StringUser) Unmarshal(dAtA []byte) error {
} }
return nil return nil
} }
func (m *CopyFileRequest) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowAgent
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: CopyFileRequest: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: CopyFileRequest: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Path", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowAgent
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthAgent
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Path = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 2:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field FileSize", wireType)
}
m.FileSize = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowAgent
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.FileSize |= (int64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
case 3:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field FileMode", wireType)
}
m.FileMode = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowAgent
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.FileMode |= (uint32(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
case 4:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field DirMode", wireType)
}
m.DirMode = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowAgent
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.DirMode |= (uint32(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
case 5:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Uid", wireType)
}
m.Uid = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowAgent
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.Uid |= (int32(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
case 6:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Gid", wireType)
}
m.Gid = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowAgent
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.Gid |= (int32(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
case 7:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Offset", wireType)
}
m.Offset = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowAgent
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.Offset |= (int64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
case 8:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowAgent
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthAgent
}
postIndex := iNdEx + byteLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...)
if m.Data == nil {
m.Data = []byte{}
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipAgent(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthAgent
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipAgent(dAtA []byte) (n int, err error) { func skipAgent(dAtA []byte) (n int, err error) {
l := len(dAtA) l := len(dAtA)
iNdEx := 0 iNdEx := 0
@ -11510,161 +11944,168 @@ var (
func init() { proto.RegisterFile("agent.proto", fileDescriptorAgent) } func init() { proto.RegisterFile("agent.proto", fileDescriptorAgent) }
var fileDescriptorAgent = []byte{ var fileDescriptorAgent = []byte{
// 2493 bytes of a gzipped FileDescriptorProto // 2596 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x58, 0x5b, 0x6f, 0x1b, 0xc7, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x58, 0x5f, 0x6f, 0x24, 0x47,
0xf5, 0x07, 0x2f, 0xba, 0xf0, 0x90, 0x14, 0xc5, 0x91, 0x2c, 0x33, 0x74, 0xe2, 0xbf, 0xb2, 0xce, 0x11, 0xd7, 0xfe, 0xf1, 0x7a, 0xb7, 0x76, 0xd7, 0xeb, 0x6d, 0xfb, 0x7c, 0x9b, 0xbd, 0x24, 0x5c,
0xdf, 0x56, 0x9a, 0x86, 0x6a, 0xe4, 0xa0, 0x09, 0x6c, 0xa4, 0x86, 0x75, 0x81, 0xa4, 0x26, 0xae, 0x26, 0xe1, 0xe2, 0x10, 0xb2, 0x26, 0x97, 0x88, 0x84, 0x9c, 0xc2, 0xe9, 0xce, 0x67, 0xce, 0x26,
0xd5, 0xa5, 0x05, 0x17, 0x28, 0x8a, 0xc5, 0x6a, 0x77, 0x4c, 0x4e, 0xc4, 0xdd, 0xd9, 0xec, 0xcc, 0x39, 0xce, 0x8c, 0x63, 0x05, 0x09, 0xa1, 0xd1, 0x78, 0xa6, 0xbd, 0xee, 0x78, 0x67, 0x7a, 0xd2,
0xca, 0x62, 0x0a, 0x14, 0x7d, 0x6a, 0x3f, 0x45, 0xbf, 0x40, 0xd1, 0xb7, 0x7e, 0x85, 0x3e, 0xe4, 0xdd, 0xe3, 0xbb, 0x0d, 0x12, 0xe2, 0x89, 0x6f, 0xc1, 0x17, 0x40, 0xbc, 0xf1, 0x0d, 0x10, 0x0f,
0xb1, 0xef, 0x05, 0x8a, 0xc2, 0x1f, 0xa1, 0x9f, 0xa0, 0x98, 0xdb, 0x5e, 0x78, 0x91, 0x53, 0x45, 0x11, 0x4f, 0xbc, 0x23, 0x21, 0x94, 0x8f, 0xc0, 0x27, 0x40, 0xfd, 0x6f, 0xfe, 0xec, 0x1f, 0x5f,
0x40, 0x5f, 0x16, 0x7b, 0xce, 0x9c, 0xf9, 0x9d, 0xcb, 0xcc, 0x9c, 0x39, 0x73, 0xa0, 0xee, 0x0e, 0x70, 0x2c, 0xf1, 0x32, 0x9a, 0xaa, 0xae, 0xfe, 0x75, 0x55, 0x75, 0x77, 0x75, 0x55, 0x41, 0xdb,
0x70, 0xc8, 0x7b, 0x51, 0x4c, 0x39, 0x45, 0xd5, 0x41, 0x1c, 0x79, 0xdd, 0x1a, 0xf5, 0x88, 0x62, 0x1f, 0xe3, 0x58, 0x8c, 0x12, 0x46, 0x05, 0x45, 0xf5, 0x31, 0x4b, 0x82, 0x61, 0x8b, 0x06, 0x44,
0x74, 0x7f, 0x3a, 0x20, 0x7c, 0x98, 0x9c, 0xf5, 0x3c, 0x1a, 0x6c, 0x9f, 0xbb, 0xdc, 0xfd, 0xd8, 0x33, 0x86, 0x3f, 0x1e, 0x13, 0x71, 0x96, 0x9e, 0x8c, 0x02, 0x1a, 0xed, 0x9c, 0xfb, 0xc2, 0x7f,
0xa3, 0x21, 0x77, 0x49, 0x88, 0x63, 0xb6, 0x2d, 0x27, 0x6e, 0x47, 0xe7, 0x83, 0x6d, 0x3e, 0x8e, 0x27, 0xa0, 0xb1, 0xf0, 0x49, 0x8c, 0x19, 0xdf, 0x51, 0x13, 0x77, 0x92, 0xf3, 0xf1, 0x8e, 0x98,
0x30, 0x53, 0x5f, 0x3d, 0xef, 0xce, 0x80, 0xd2, 0xc1, 0x08, 0x6f, 0x4b, 0xea, 0x2c, 0x79, 0xb5, 0x26, 0x98, 0xeb, 0xaf, 0x99, 0x77, 0x6b, 0x4c, 0xe9, 0x78, 0x82, 0x77, 0x14, 0x75, 0x92, 0x9e,
0x8d, 0x83, 0x88, 0x8f, 0xd5, 0xa0, 0xf5, 0xa7, 0x32, 0x6c, 0xec, 0xc5, 0xd8, 0xe5, 0x78, 0xcf, 0xee, 0xe0, 0x28, 0x11, 0x53, 0x3d, 0xe8, 0xfc, 0xb1, 0x0a, 0x5b, 0xbb, 0x0c, 0xfb, 0x02, 0xef,
0xa0, 0xd9, 0xf8, 0x9b, 0x04, 0x33, 0x8e, 0xde, 0x87, 0x46, 0xaa, 0xc1, 0x21, 0x7e, 0xa7, 0xb4, 0x5a, 0x34, 0x17, 0x7f, 0x99, 0x62, 0x2e, 0xd0, 0x6b, 0xd0, 0xc9, 0x56, 0xf0, 0x48, 0x38, 0xa8,
0x59, 0xda, 0xaa, 0xd9, 0xf5, 0x94, 0x77, 0xec, 0xa3, 0xdb, 0xb0, 0x84, 0x2f, 0xb1, 0x27, 0x46, 0xdc, 0xae, 0x6c, 0xb7, 0xdc, 0x76, 0xc6, 0x3b, 0x08, 0xd1, 0x4d, 0x58, 0xc5, 0xcf, 0x71, 0x20,
0xcb, 0x72, 0x74, 0x51, 0x90, 0xc7, 0x3e, 0xfa, 0x04, 0xea, 0x8c, 0xc7, 0x24, 0x1c, 0x38, 0x09, 0x47, 0xab, 0x6a, 0xb4, 0x21, 0xc9, 0x83, 0x10, 0xbd, 0x0b, 0x6d, 0x2e, 0x18, 0x89, 0xc7, 0x5e,
0xc3, 0x71, 0xa7, 0xb2, 0x59, 0xda, 0xaa, 0xef, 0xac, 0xf6, 0x84, 0x4b, 0xbd, 0xbe, 0x1c, 0x38, 0xca, 0x31, 0x1b, 0xd4, 0x6e, 0x57, 0xb6, 0xdb, 0x77, 0xd7, 0x47, 0xd2, 0xa4, 0xd1, 0x91, 0x1a,
0x65, 0x38, 0xb6, 0x81, 0xa5, 0xff, 0xe8, 0x3e, 0x2c, 0xf9, 0xf8, 0x82, 0x78, 0x98, 0x75, 0xaa, 0x38, 0xe6, 0x98, 0xb9, 0xc0, 0xb3, 0x7f, 0x74, 0x07, 0x56, 0x43, 0x7c, 0x41, 0x02, 0xcc, 0x07,
0x9b, 0x95, 0xad, 0xfa, 0x4e, 0x43, 0x89, 0xef, 0x4b, 0xa6, 0x6d, 0x06, 0xd1, 0x87, 0xb0, 0xcc, 0xf5, 0xdb, 0xb5, 0xed, 0xf6, 0xdd, 0x8e, 0x16, 0x7f, 0xa4, 0x98, 0xae, 0x1d, 0x44, 0x6f, 0x41,
0x38, 0x8d, 0xdd, 0x01, 0x66, 0x9d, 0x05, 0x29, 0xd8, 0x34, 0xb8, 0x92, 0x6b, 0xa7, 0xc3, 0xe8, 0x93, 0x0b, 0xca, 0xfc, 0x31, 0xe6, 0x83, 0x15, 0x25, 0xd8, 0xb5, 0xb8, 0x8a, 0xeb, 0x66, 0xc3,
0x5d, 0xa8, 0x3c, 0xdf, 0x3b, 0xee, 0x2c, 0x4a, 0xed, 0xa0, 0xa5, 0x22, 0xec, 0xd9, 0x82, 0x8d, 0xe8, 0x65, 0xa8, 0x3d, 0xdd, 0x3d, 0x18, 0x34, 0xd4, 0xea, 0x60, 0xa4, 0x12, 0x1c, 0xb8, 0x92,
0xee, 0x41, 0x93, 0xb9, 0xa1, 0x7f, 0x46, 0x2f, 0x9d, 0x88, 0xf8, 0x21, 0xeb, 0x2c, 0x6d, 0x96, 0x8d, 0x5e, 0x87, 0x2e, 0xf7, 0xe3, 0xf0, 0x84, 0x3e, 0xf7, 0x12, 0x12, 0xc6, 0x7c, 0xb0, 0x7a,
0xb6, 0x96, 0xed, 0x86, 0x66, 0x9e, 0x08, 0x9e, 0xf5, 0x08, 0x6e, 0xf5, 0xb9, 0x1b, 0xf3, 0x6b, 0xbb, 0xb2, 0xdd, 0x74, 0x3b, 0x86, 0x79, 0x28, 0x79, 0xce, 0x47, 0x70, 0xe3, 0x48, 0xf8, 0x4c,
0x44, 0xc7, 0x3a, 0x85, 0x0d, 0x1b, 0x07, 0xf4, 0xe2, 0x5a, 0xa1, 0xed, 0xc0, 0x12, 0x27, 0x01, 0x5c, 0xc1, 0x3b, 0xce, 0x31, 0x6c, 0xb9, 0x38, 0xa2, 0x17, 0x57, 0x72, 0xed, 0x00, 0x56, 0x05,
0xa6, 0x09, 0x97, 0xa1, 0x6d, 0xda, 0x86, 0xb4, 0xfe, 0x52, 0x02, 0x74, 0x70, 0x89, 0xbd, 0x93, 0x89, 0x30, 0x4d, 0x85, 0x72, 0x6d, 0xd7, 0xb5, 0xa4, 0xf3, 0xe7, 0x0a, 0xa0, 0xbd, 0xe7, 0x38,
0x98, 0x7a, 0x98, 0xb1, 0xff, 0xd1, 0x72, 0x3d, 0x80, 0xa5, 0x48, 0x19, 0xd0, 0xa9, 0x4a, 0x71, 0x38, 0x64, 0x34, 0xc0, 0x9c, 0xff, 0x9f, 0xb6, 0xeb, 0x4d, 0x58, 0x4d, 0xb4, 0x02, 0x83, 0xba,
0xbd, 0x0a, 0xc6, 0x2a, 0x33, 0x6a, 0x7d, 0x0d, 0xeb, 0x7d, 0x32, 0x08, 0xdd, 0xd1, 0x0d, 0xda, 0x12, 0x37, 0xbb, 0x60, 0xb5, 0xb2, 0xa3, 0xce, 0x17, 0xb0, 0x79, 0x44, 0xc6, 0xb1, 0x3f, 0xb9,
0xbb, 0x01, 0x8b, 0x4c, 0x62, 0x4a, 0x53, 0x9b, 0xb6, 0xa6, 0xac, 0x13, 0x40, 0x2f, 0x5d, 0xc2, 0x46, 0x7d, 0xb7, 0xa0, 0xc1, 0x15, 0xa6, 0x52, 0xb5, 0xeb, 0x1a, 0xca, 0x39, 0x04, 0xf4, 0xb9,
0x6f, 0x4e, 0x93, 0xf5, 0x31, 0xac, 0x15, 0x10, 0x59, 0x44, 0x43, 0x86, 0xa5, 0x01, 0xdc, 0xe5, 0x4f, 0xc4, 0xf5, 0xad, 0xe4, 0xbc, 0x03, 0x1b, 0x25, 0x44, 0x9e, 0xd0, 0x98, 0x63, 0xa5, 0x80,
0x09, 0x93, 0x60, 0x0b, 0xb6, 0xa6, 0x2c, 0x0c, 0xeb, 0x5f, 0x11, 0x66, 0xc4, 0xf1, 0x7f, 0x63, 0xf0, 0x45, 0xca, 0x15, 0xd8, 0x8a, 0x6b, 0x28, 0x07, 0xc3, 0xe6, 0xa7, 0x84, 0x5b, 0x71, 0xfc,
0xc2, 0x06, 0x2c, 0xbe, 0xa2, 0x71, 0xe0, 0x72, 0x63, 0x81, 0xa2, 0x10, 0x82, 0xaa, 0x1b, 0x0f, 0xbf, 0xa8, 0xb0, 0x05, 0x8d, 0x53, 0xca, 0x22, 0x5f, 0x58, 0x0d, 0x34, 0x85, 0x10, 0xd4, 0x7d,
0x58, 0xa7, 0xb2, 0x59, 0xd9, 0xaa, 0xd9, 0xf2, 0x5f, 0xec, 0xca, 0x09, 0x35, 0xda, 0xae, 0xf7, 0x36, 0xe6, 0x83, 0xda, 0xed, 0xda, 0x76, 0xcb, 0x55, 0xff, 0xf2, 0x54, 0xce, 0x2c, 0x63, 0xf4,
0xa1, 0xa1, 0xe3, 0xee, 0x8c, 0x08, 0xe3, 0x52, 0x4f, 0xc3, 0xae, 0x6b, 0x9e, 0x98, 0x63, 0x51, 0x7a, 0x0d, 0x3a, 0xc6, 0xef, 0xde, 0x84, 0x70, 0xa1, 0xd6, 0xe9, 0xb8, 0x6d, 0xc3, 0x93, 0x73,
0xd8, 0x38, 0x8d, 0xfc, 0x6b, 0x1e, 0xf8, 0x1d, 0xa8, 0xc5, 0x98, 0xd1, 0x24, 0x16, 0xc7, 0xb4, 0x1c, 0x0a, 0x5b, 0xc7, 0x49, 0x78, 0xc5, 0x0b, 0x7f, 0x17, 0x5a, 0x0c, 0x73, 0x9a, 0x32, 0x79,
0x2c, 0xd7, 0x7d, 0x5d, 0xad, 0xfb, 0x57, 0x24, 0x4c, 0x2e, 0x6d, 0x33, 0x66, 0x67, 0x62, 0xfa, 0x4d, 0xab, 0x6a, 0xdf, 0x37, 0xf5, 0xbe, 0x7f, 0x4a, 0xe2, 0xf4, 0xb9, 0x6b, 0xc7, 0xdc, 0x5c,
0x08, 0x71, 0x76, 0x9d, 0x23, 0xf4, 0x08, 0x6e, 0x9d, 0xb8, 0x09, 0xbb, 0x8e, 0xad, 0xd6, 0x63, 0xcc, 0x5c, 0x21, 0xc1, 0xaf, 0x72, 0x85, 0x3e, 0x82, 0x1b, 0x87, 0x7e, 0xca, 0xaf, 0xa2, 0xab,
0x71, 0xfc, 0x58, 0x12, 0x5c, 0x6b, 0xf2, 0x9f, 0x4b, 0xb0, 0xbc, 0x17, 0x25, 0xa7, 0xcc, 0x1d, 0x73, 0x4f, 0x5e, 0x3f, 0x9e, 0x46, 0x57, 0x9a, 0xfc, 0xa7, 0x0a, 0x34, 0x77, 0x93, 0xf4, 0x98,
0x60, 0xf4, 0x7f, 0x50, 0xe7, 0x94, 0xbb, 0x23, 0x27, 0x11, 0xa4, 0x14, 0xaf, 0xda, 0x20, 0x59, 0xfb, 0x63, 0x8c, 0xbe, 0x07, 0x6d, 0x41, 0x85, 0x3f, 0xf1, 0x52, 0x49, 0x2a, 0xf1, 0xba, 0x0b,
0x4a, 0x40, 0x84, 0x1d, 0xc7, 0x5e, 0x94, 0x68, 0x89, 0xf2, 0x66, 0x65, 0xab, 0x6a, 0xd7, 0x15, 0x8a, 0xa5, 0x05, 0xa4, 0xdb, 0x31, 0x0b, 0x92, 0xd4, 0x48, 0x54, 0x6f, 0xd7, 0xb6, 0xeb, 0x6e,
0x4f, 0x89, 0xf4, 0x60, 0x4d, 0x8e, 0x39, 0x24, 0x74, 0xce, 0x71, 0x1c, 0xe2, 0x51, 0x40, 0x7d, 0x5b, 0xf3, 0xb4, 0xc8, 0x08, 0x36, 0xd4, 0x98, 0x47, 0x62, 0xef, 0x1c, 0xb3, 0x18, 0x4f, 0x22,
0x2c, 0xf7, 0x6f, 0xd5, 0x6e, 0xcb, 0xa1, 0xe3, 0xf0, 0xcb, 0x74, 0x00, 0xfd, 0x08, 0xda, 0xa9, 0x1a, 0x62, 0x75, 0x7e, 0xeb, 0x6e, 0x5f, 0x0d, 0x1d, 0xc4, 0x9f, 0x64, 0x03, 0xe8, 0x07, 0xd0,
0xbc, 0x38, 0x94, 0x52, 0xba, 0x2a, 0xa5, 0x5b, 0x5a, 0xfa, 0x54, 0xb3, 0xad, 0xdf, 0xc1, 0xca, 0xcf, 0xe4, 0xe5, 0xa5, 0x54, 0xd2, 0x75, 0x25, 0xdd, 0x33, 0xd2, 0xc7, 0x86, 0xed, 0xfc, 0x0e,
0x8b, 0x61, 0x4c, 0x39, 0x1f, 0x91, 0x70, 0xb0, 0xef, 0x72, 0x57, 0x64, 0x8f, 0x08, 0xc7, 0x84, 0xd6, 0x3e, 0x3b, 0x63, 0x54, 0x88, 0x09, 0x89, 0xc7, 0x8f, 0x7c, 0xe1, 0xcb, 0xe8, 0x91, 0x60,
0xfa, 0x4c, 0x5b, 0x6b, 0x48, 0xf4, 0x11, 0xb4, 0xb9, 0x92, 0xc5, 0xbe, 0x63, 0x64, 0xca, 0x52, 0x46, 0x68, 0xc8, 0x8d, 0xb6, 0x96, 0x44, 0x6f, 0x43, 0x5f, 0x68, 0x59, 0x1c, 0x7a, 0x56, 0xa6,
0x66, 0x35, 0x1d, 0x38, 0xd1, 0xc2, 0xff, 0x0f, 0x2b, 0x99, 0xb0, 0xc8, 0x3f, 0xda, 0xde, 0x66, 0xaa, 0x64, 0xd6, 0xb3, 0x81, 0x43, 0x23, 0xfc, 0x7d, 0x58, 0xcb, 0x85, 0x65, 0xfc, 0x31, 0xfa,
0xca, 0x7d, 0x41, 0x02, 0x6c, 0x5d, 0xc8, 0x58, 0xc9, 0x45, 0x46, 0x1f, 0x41, 0x2d, 0x8b, 0x43, 0x76, 0x33, 0xee, 0x67, 0x24, 0xc2, 0xce, 0x85, 0xf2, 0x95, 0xda, 0x64, 0xf4, 0x36, 0xb4, 0x72,
0x49, 0xee, 0x90, 0x15, 0xb5, 0x43, 0x4c, 0x38, 0xed, 0xe5, 0x34, 0x28, 0x5f, 0x40, 0x8b, 0xa7, 0x3f, 0x54, 0xd4, 0x09, 0x59, 0xd3, 0x27, 0xc4, 0xba, 0xd3, 0x6d, 0x66, 0x4e, 0xf9, 0x18, 0x7a,
0x86, 0x3b, 0xbe, 0xcb, 0xdd, 0xe2, 0xa6, 0x2a, 0x7a, 0x65, 0xaf, 0xf0, 0x02, 0x6d, 0x3d, 0x86, 0x22, 0x53, 0xdc, 0x0b, 0x7d, 0xe1, 0x97, 0x0f, 0x55, 0xd9, 0x2a, 0x77, 0x4d, 0x94, 0x68, 0xe7,
0xda, 0x09, 0xf1, 0x99, 0x52, 0xdc, 0x81, 0x25, 0x2f, 0x89, 0x63, 0x1c, 0x72, 0xe3, 0xb2, 0x26, 0x1e, 0xb4, 0x0e, 0x49, 0xc8, 0xf5, 0xc2, 0x03, 0x58, 0x0d, 0x52, 0xc6, 0x70, 0x2c, 0xac, 0xc9,
0xd1, 0x3a, 0x2c, 0x8c, 0x48, 0x40, 0xb8, 0x76, 0x53, 0x11, 0x16, 0x05, 0x78, 0x86, 0x03, 0x1a, 0x86, 0x44, 0x9b, 0xb0, 0x32, 0x21, 0x11, 0x11, 0xc6, 0x4c, 0x4d, 0x38, 0x14, 0xe0, 0x09, 0x8e,
0x8f, 0x65, 0xc0, 0xd6, 0x61, 0x21, 0xbf, 0xb8, 0x8a, 0x40, 0x77, 0xa0, 0x16, 0xb8, 0x97, 0xe9, 0x28, 0x9b, 0x2a, 0x87, 0x6d, 0xc2, 0x4a, 0x71, 0x73, 0x35, 0x81, 0x6e, 0x41, 0x2b, 0xf2, 0x9f,
0xa2, 0x8a, 0x91, 0xe5, 0xc0, 0xbd, 0x54, 0xc6, 0x77, 0x60, 0xe9, 0x95, 0x4b, 0x46, 0x5e, 0xc8, 0x67, 0x9b, 0x2a, 0x47, 0x9a, 0x91, 0xff, 0x5c, 0x2b, 0x3f, 0x80, 0xd5, 0x53, 0x9f, 0x4c, 0x82,
0x75, 0x54, 0x0c, 0x99, 0x29, 0xac, 0xe6, 0x15, 0xfe, 0xad, 0x0c, 0x75, 0xa5, 0x51, 0x19, 0xbc, 0x58, 0x18, 0xaf, 0x58, 0x32, 0x5f, 0xb0, 0x5e, 0x5c, 0xf0, 0x6f, 0x55, 0x68, 0xeb, 0x15, 0xb5,
0x0e, 0x0b, 0x9e, 0xeb, 0x0d, 0x53, 0x95, 0x92, 0x40, 0xf7, 0x8d, 0x21, 0xe5, 0x7c, 0x12, 0xce, 0xc2, 0x9b, 0xb0, 0x12, 0xf8, 0xc1, 0x59, 0xb6, 0xa4, 0x22, 0xd0, 0x1d, 0xab, 0x48, 0xb5, 0x18,
0x2c, 0x35, 0xa6, 0x6d, 0x03, 0xb0, 0xd7, 0x6e, 0xa4, 0x6d, 0xab, 0xcc, 0x11, 0xae, 0x09, 0x19, 0x84, 0x73, 0x4d, 0xad, 0x6a, 0x3b, 0x00, 0xfc, 0x99, 0x9f, 0x18, 0xdd, 0x6a, 0x4b, 0x84, 0x5b,
0x65, 0xee, 0x43, 0x68, 0xa8, 0x7d, 0xa7, 0xa7, 0x54, 0xe7, 0x4c, 0xa9, 0x2b, 0x29, 0x35, 0xe9, 0x52, 0x46, 0xab, 0xfb, 0x1e, 0x74, 0xf4, 0xb9, 0x33, 0x53, 0xea, 0x4b, 0xa6, 0xb4, 0xb5, 0x94,
0x1e, 0x34, 0x13, 0x86, 0x9d, 0x21, 0xc1, 0xb1, 0x1b, 0x7b, 0xc3, 0x71, 0x67, 0x41, 0xdd, 0x91, 0x9e, 0xf4, 0x3a, 0x74, 0x53, 0x8e, 0xbd, 0x33, 0x82, 0x99, 0xcf, 0x82, 0xb3, 0xe9, 0x60, 0x45,
0x09, 0xc3, 0x47, 0x86, 0x87, 0x76, 0x60, 0x41, 0xa4, 0x3f, 0xd6, 0x59, 0x94, 0xd7, 0xf1, 0xbb, 0xbf, 0x91, 0x29, 0xc7, 0xfb, 0x96, 0x87, 0xee, 0xc2, 0x8a, 0x0c, 0x7f, 0x7c, 0xd0, 0x50, 0xcf,
0x79, 0x48, 0xe9, 0x6a, 0x4f, 0x7e, 0x0f, 0x42, 0x1e, 0x8f, 0x6d, 0x25, 0xda, 0xfd, 0x1c, 0x20, 0xf1, 0xcb, 0x45, 0x48, 0x65, 0xea, 0x48, 0x7d, 0xf7, 0x62, 0xc1, 0xa6, 0xae, 0x16, 0x1d, 0x7e,
0x63, 0xa2, 0x55, 0xa8, 0x9c, 0xe3, 0xb1, 0x3e, 0x87, 0xe2, 0x57, 0x04, 0xe7, 0xc2, 0x1d, 0x25, 0x08, 0x90, 0x33, 0xd1, 0x3a, 0xd4, 0xce, 0xf1, 0xd4, 0xdc, 0x43, 0xf9, 0x2b, 0x9d, 0x73, 0xe1,
0x26, 0xea, 0x8a, 0x78, 0x54, 0xfe, 0xbc, 0x64, 0x79, 0xd0, 0xda, 0x1d, 0x9d, 0x13, 0x9a, 0x9b, 0x4f, 0x52, 0xeb, 0x75, 0x4d, 0x7c, 0x54, 0xfd, 0xb0, 0xe2, 0x04, 0xd0, 0x7b, 0x38, 0x39, 0x27,
0xbe, 0x0e, 0x0b, 0x81, 0xfb, 0x35, 0x8d, 0x4d, 0x24, 0x25, 0x21, 0xb9, 0x24, 0xa4, 0xb1, 0x81, 0xb4, 0x30, 0x7d, 0x13, 0x56, 0x22, 0xff, 0x0b, 0xca, 0xac, 0x27, 0x15, 0xa1, 0xb8, 0x24, 0xa6,
0x90, 0x04, 0x5a, 0x81, 0x32, 0x8d, 0x64, 0xbc, 0x6a, 0x76, 0x99, 0x46, 0x99, 0xa2, 0x6a, 0x4e, 0xcc, 0x42, 0x28, 0x02, 0xad, 0x41, 0x95, 0x26, 0xca, 0x5f, 0x2d, 0xb7, 0x4a, 0x93, 0x7c, 0xa1,
0x91, 0xf5, 0xcf, 0x2a, 0x40, 0xa6, 0x05, 0xd9, 0xd0, 0x25, 0xd4, 0x61, 0x38, 0x16, 0x25, 0x88, 0x7a, 0x61, 0x21, 0xe7, 0x5f, 0x75, 0x80, 0x7c, 0x15, 0xe4, 0xc2, 0x90, 0x50, 0x8f, 0x63, 0x26,
0x73, 0x36, 0xe6, 0x98, 0x39, 0x31, 0xf6, 0x92, 0x98, 0x91, 0x0b, 0xb1, 0x7e, 0xc2, 0xed, 0x5b, 0x53, 0x10, 0xef, 0x64, 0x2a, 0x30, 0xf7, 0x18, 0x0e, 0x52, 0xc6, 0xc9, 0x85, 0xdc, 0x3f, 0x69,
0xca, 0xed, 0x09, 0xdb, 0xec, 0xdb, 0x84, 0xf6, 0xd5, 0xbc, 0x5d, 0x31, 0xcd, 0x36, 0xb3, 0xd0, 0xf6, 0x0d, 0x6d, 0xf6, 0x8c, 0x6e, 0xee, 0x4d, 0x42, 0x8f, 0xf4, 0xbc, 0x87, 0x72, 0x9a, 0x6b,
0x31, 0xdc, 0xca, 0x30, 0xfd, 0x1c, 0x5c, 0xf9, 0x2a, 0xb8, 0xb5, 0x14, 0xce, 0xcf, 0xa0, 0x0e, 0x67, 0xa1, 0x03, 0xb8, 0x91, 0x63, 0x86, 0x05, 0xb8, 0xea, 0x65, 0x70, 0x1b, 0x19, 0x5c, 0x98,
0x60, 0x8d, 0x50, 0xe7, 0x9b, 0x04, 0x27, 0x05, 0xa0, 0xca, 0x55, 0x40, 0x6d, 0x42, 0x7f, 0x29, 0x43, 0xed, 0xc1, 0x06, 0xa1, 0xde, 0x97, 0x29, 0x4e, 0x4b, 0x40, 0xb5, 0xcb, 0x80, 0xfa, 0x84,
0x27, 0x64, 0x30, 0x27, 0xf0, 0x4e, 0xce, 0x4b, 0x71, 0xdc, 0x73, 0x60, 0xd5, 0xab, 0xc0, 0x36, 0xfe, 0x52, 0x4d, 0xc8, 0x61, 0x0e, 0xe1, 0xa5, 0x82, 0x95, 0xf2, 0xba, 0x17, 0xc0, 0xea, 0x97,
0x52, 0xab, 0x44, 0x3e, 0xc8, 0x10, 0x7f, 0x0e, 0x1b, 0x84, 0x3a, 0xaf, 0x5d, 0xc2, 0x27, 0xe1, 0x81, 0x6d, 0x65, 0x5a, 0xc9, 0x78, 0x90, 0x23, 0xfe, 0x1c, 0xb6, 0x08, 0xf5, 0x9e, 0xf9, 0x44,
0x16, 0xde, 0xe2, 0xa4, 0xb8, 0x74, 0x8b, 0x58, 0xca, 0xc9, 0x00, 0xc7, 0x83, 0x82, 0x93, 0x8b, 0xcc, 0xc2, 0xad, 0xbc, 0xc0, 0x48, 0xf9, 0xe8, 0x96, 0xb1, 0xb4, 0x91, 0x11, 0x66, 0xe3, 0x92,
0x6f, 0x71, 0xf2, 0x99, 0x9c, 0x90, 0xc1, 0x3c, 0x85, 0x36, 0xa1, 0x93, 0xd6, 0x2c, 0x5d, 0x05, 0x91, 0x8d, 0x17, 0x18, 0xf9, 0x44, 0x4d, 0xc8, 0x61, 0x1e, 0x40, 0x9f, 0xd0, 0x59, 0x6d, 0x56,
0xd2, 0x22, 0xb4, 0x68, 0xc9, 0x2e, 0xb4, 0x19, 0xf6, 0x38, 0x8d, 0xf3, 0x9b, 0x60, 0xf9, 0x2a, 0x2f, 0x03, 0xe9, 0x11, 0x5a, 0xd6, 0xe4, 0x21, 0xf4, 0x39, 0x0e, 0x04, 0x65, 0xc5, 0x43, 0xd0,
0x88, 0x55, 0x2d, 0x9f, 0x62, 0x58, 0xbf, 0x86, 0xc6, 0x51, 0x32, 0xc0, 0x7c, 0x74, 0x96, 0x26, 0xbc, 0x0c, 0x62, 0xdd, 0xc8, 0x67, 0x18, 0xce, 0xaf, 0xa1, 0xb3, 0x9f, 0x8e, 0xb1, 0x98, 0x9c,
0x83, 0x1b, 0xcb, 0x3f, 0xd6, 0xbf, 0xcb, 0x50, 0xdf, 0x1b, 0xc4, 0x34, 0x89, 0x0a, 0x39, 0x59, 0x64, 0xc1, 0xe0, 0xda, 0xe2, 0x8f, 0xf3, 0x9f, 0x2a, 0xb4, 0x77, 0xc7, 0x8c, 0xa6, 0x49, 0x29,
0x1d, 0xd2, 0xc9, 0x9c, 0x2c, 0x45, 0x64, 0x4e, 0x56, 0xc2, 0x9f, 0x42, 0x23, 0x90, 0x47, 0x57, 0x26, 0xeb, 0x4b, 0x3a, 0x1b, 0x93, 0x95, 0x88, 0x8a, 0xc9, 0x5a, 0xf8, 0x7d, 0xe8, 0x44, 0xea,
0xcb, 0xab, 0x3c, 0xd4, 0x9e, 0x3a, 0xd4, 0x76, 0x3d, 0xc8, 0x25, 0xb3, 0x1e, 0x40, 0x44, 0x7c, 0xea, 0x1a, 0x79, 0x1d, 0x87, 0xfa, 0x73, 0x97, 0xda, 0x6d, 0x47, 0x85, 0x60, 0x36, 0x02, 0x48,
0xa6, 0xe7, 0xa8, 0x74, 0xd4, 0xd2, 0x15, 0xa1, 0x49, 0xd1, 0x76, 0x2d, 0x4a, 0xb3, 0xf5, 0x27, 0x48, 0xc8, 0xcd, 0x1c, 0x1d, 0x8e, 0x7a, 0x26, 0x23, 0xb4, 0x21, 0xda, 0x6d, 0x25, 0x59, 0xb4,
0x50, 0x3f, 0x13, 0x41, 0xd2, 0x13, 0x0a, 0xc9, 0x28, 0x8b, 0x9e, 0x0d, 0x67, 0xd9, 0x21, 0x3c, 0x7e, 0x17, 0xda, 0x27, 0xd2, 0x49, 0x66, 0x42, 0x29, 0x18, 0xe5, 0xde, 0x73, 0xe1, 0x24, 0xbf,
0x82, 0xe6, 0x50, 0x85, 0x4c, 0x4f, 0x52, 0x7b, 0xe8, 0x9e, 0xf6, 0x24, 0xf3, 0xb7, 0x97, 0x8f, 0x84, 0xfb, 0xd0, 0x3d, 0xd3, 0x2e, 0x33, 0x93, 0xf4, 0x19, 0x7a, 0xdd, 0x58, 0x92, 0xdb, 0x3b,
0xac, 0x5a, 0x80, 0xc6, 0x30, 0xc7, 0xea, 0xf6, 0xa1, 0x3d, 0x25, 0x32, 0x23, 0x07, 0x6d, 0xe5, 0x2a, 0x7a, 0x56, 0x6f, 0x40, 0xe7, 0xac, 0xc0, 0x1a, 0x1e, 0x41, 0x7f, 0x4e, 0x64, 0x41, 0x0c,
0x73, 0x50, 0x7d, 0x07, 0x29, 0x45, 0xf9, 0x99, 0xf9, 0xbc, 0xf4, 0x0b, 0xd8, 0x98, 0x2c, 0x73, 0xda, 0x2e, 0xc6, 0xa0, 0xf6, 0x5d, 0xa4, 0x17, 0x2a, 0xce, 0x2c, 0xc6, 0xa5, 0x5f, 0xc0, 0xd6,
0x74, 0x51, 0xf6, 0x29, 0x34, 0x3c, 0x69, 0x5d, 0x61, 0x05, 0xda, 0x53, 0x76, 0xdb, 0x75, 0x2f, 0x6c, 0x9a, 0x63, 0x92, 0xb2, 0xf7, 0xa1, 0x13, 0x28, 0xed, 0x4a, 0x3b, 0xd0, 0x9f, 0xd3, 0xdb,
0x23, 0x2c, 0x1f, 0xd0, 0xcb, 0x98, 0x70, 0xdc, 0xe7, 0x31, 0x76, 0x83, 0x9b, 0xa8, 0x9a, 0x11, 0x6d, 0x07, 0x39, 0xe1, 0x84, 0x80, 0x3e, 0x67, 0x44, 0xe0, 0x23, 0xc1, 0xb0, 0x1f, 0x5d, 0x47,
0x54, 0xe5, 0x15, 0x5b, 0x91, 0x45, 0xa1, 0xfc, 0xb7, 0x1e, 0xc0, 0x5a, 0x41, 0x8b, 0x36, 0x79, 0xd6, 0x8c, 0xa0, 0xae, 0x9e, 0xd8, 0x9a, 0x4a, 0x0a, 0xd5, 0xbf, 0xf3, 0x26, 0x6c, 0x94, 0x56,
0x15, 0x2a, 0x23, 0x1c, 0x4a, 0xf4, 0xa6, 0x2d, 0x7e, 0x2d, 0x17, 0xda, 0x36, 0x76, 0xfd, 0x9b, 0x31, 0x2a, 0xaf, 0x43, 0x6d, 0x82, 0x63, 0x85, 0xde, 0x75, 0xe5, 0xaf, 0xe3, 0x43, 0xdf, 0xc5,
0xb3, 0x46, 0xab, 0xa8, 0x64, 0x2a, 0xb6, 0x00, 0xe5, 0x55, 0x68, 0x53, 0x8c, 0xd5, 0xa5, 0x9c, 0x7e, 0x78, 0x7d, 0xda, 0x98, 0x25, 0x6a, 0xf9, 0x12, 0xdb, 0x80, 0x8a, 0x4b, 0x18, 0x55, 0xac,
0xd5, 0xcf, 0xa1, 0xbd, 0x37, 0xa2, 0x0c, 0xf7, 0xb9, 0x4f, 0xc2, 0x9b, 0x28, 0xf3, 0x7f, 0x0b, 0xd6, 0x95, 0x82, 0xd6, 0x4f, 0xa1, 0xbf, 0x3b, 0xa1, 0x1c, 0x1f, 0x89, 0x90, 0xc4, 0xd7, 0x91,
0x6b, 0x2f, 0xf8, 0xf8, 0xa5, 0x00, 0x63, 0xe4, 0x5b, 0x7c, 0x43, 0xfe, 0xc5, 0xf4, 0xb5, 0xf1, 0xe6, 0xff, 0x16, 0x36, 0x3e, 0x13, 0xd3, 0xcf, 0x25, 0x18, 0x27, 0x5f, 0xe1, 0x6b, 0xb2, 0x8f,
0x2f, 0xa6, 0xaf, 0x45, 0x85, 0xef, 0xd1, 0x51, 0x12, 0x84, 0x72, 0xbb, 0x37, 0x6d, 0x4d, 0x59, 0xd1, 0x67, 0xd6, 0x3e, 0x46, 0x9f, 0xc9, 0x0c, 0x3f, 0xa0, 0x93, 0x34, 0x8a, 0xd5, 0x71, 0xef,
0xff, 0x28, 0xc1, 0xba, 0x7a, 0x83, 0xf7, 0xd5, 0xd3, 0xd3, 0xa8, 0xef, 0xc2, 0xf2, 0x90, 0x32, 0xba, 0x86, 0x72, 0xfe, 0x59, 0x81, 0x4d, 0x5d, 0x83, 0x1f, 0xe9, 0xd2, 0xd3, 0x2e, 0x3f, 0x84,
0x1e, 0xba, 0x01, 0xd6, 0xaa, 0x53, 0x5a, 0xc0, 0x8b, 0x37, 0x6b, 0x59, 0xbe, 0x0a, 0xc4, 0x6f, 0xe6, 0x19, 0xe5, 0x22, 0xf6, 0x23, 0x6c, 0x96, 0xce, 0x68, 0x09, 0x2f, 0x6b, 0xd6, 0xaa, 0xaa,
0xe1, 0x61, 0x5c, 0xb9, 0xfa, 0x61, 0x3c, 0xf5, 0xf4, 0xad, 0x4e, 0x3f, 0x7d, 0xd1, 0x7b, 0x00, 0x0a, 0xe4, 0x6f, 0xa9, 0x30, 0xae, 0x5d, 0x5e, 0x18, 0xcf, 0x95, 0xbe, 0xf5, 0xf9, 0xd2, 0x17,
0x46, 0x88, 0xf8, 0xf2, 0xe2, 0xaf, 0xd9, 0x35, 0xcd, 0x39, 0xf6, 0xd1, 0x7d, 0x68, 0x0d, 0x84, 0xbd, 0x02, 0x60, 0x85, 0x48, 0xa8, 0x1e, 0xfe, 0x96, 0xdb, 0x32, 0x9c, 0x83, 0x10, 0xdd, 0x81,
0x95, 0xce, 0x90, 0xd2, 0x73, 0x27, 0x72, 0xf9, 0x50, 0x3e, 0xb4, 0x6b, 0x76, 0x53, 0xb2, 0x8f, 0xde, 0x58, 0x6a, 0xe9, 0x9d, 0x51, 0x7a, 0xee, 0x25, 0xbe, 0x38, 0x53, 0x85, 0x76, 0xcb, 0xed,
0x28, 0x3d, 0x3f, 0x71, 0xf9, 0xd0, 0xba, 0x0d, 0xb7, 0xf6, 0x31, 0xe3, 0x31, 0x1d, 0x17, 0xbd, 0x2a, 0xf6, 0x3e, 0xa5, 0xe7, 0x87, 0xbe, 0x38, 0x73, 0x6e, 0xc2, 0x8d, 0x47, 0x98, 0x0b, 0x46,
0xb3, 0x7e, 0x06, 0x70, 0x1c, 0x72, 0x1c, 0xbf, 0x72, 0xc5, 0xb3, 0xfe, 0x27, 0x79, 0x4a, 0x5f, 0xa7, 0x65, 0xeb, 0x9c, 0x9f, 0x02, 0x1c, 0xc4, 0x02, 0xb3, 0x53, 0x5f, 0x96, 0xf5, 0x3f, 0x2a,
0xa9, 0xab, 0x3d, 0xd5, 0xc7, 0x48, 0x07, 0xec, 0x9c, 0x8c, 0xd5, 0x83, 0x45, 0x9b, 0x26, 0x1c, 0x52, 0xe6, 0x49, 0x5d, 0x1f, 0xe9, 0x3e, 0x46, 0x36, 0xe0, 0x16, 0x64, 0x9c, 0x11, 0x34, 0x5c,
0x33, 0xf4, 0x81, 0xf9, 0xd3, 0xf3, 0x1a, 0x7a, 0x9e, 0x64, 0xda, 0x7a, 0xcc, 0x3a, 0x32, 0x0f, 0x9a, 0x0a, 0xcc, 0xd1, 0x1b, 0xf6, 0xcf, 0xcc, 0xeb, 0x98, 0x79, 0x8a, 0xe9, 0x9a, 0x31, 0x67,
0x9f, 0x0c, 0x4e, 0xc7, 0xb9, 0x07, 0x35, 0x62, 0x78, 0xfa, 0x74, 0x4e, 0xab, 0xce, 0x44, 0xac, 0xdf, 0x16, 0x3e, 0x39, 0x9c, 0xf1, 0xf3, 0x08, 0x5a, 0xc4, 0xf2, 0xcc, 0xed, 0x9c, 0x5f, 0x3a,
0x03, 0x58, 0x7b, 0xea, 0xfb, 0x3f, 0x18, 0xe6, 0xc8, 0xf4, 0x07, 0x7e, 0x30, 0xd2, 0x63, 0x58, 0x17, 0x71, 0xf6, 0x60, 0xe3, 0x41, 0x18, 0x7e, 0x67, 0x98, 0x7d, 0xdb, 0x1f, 0xf8, 0xce, 0x48,
0x53, 0xae, 0x29, 0x57, 0x0d, 0xcc, 0x07, 0xb0, 0x18, 0x9b, 0xb8, 0x94, 0xb2, 0x8e, 0x8a, 0x16, 0xf7, 0x60, 0x43, 0x9b, 0xa6, 0x4d, 0xb5, 0x30, 0x6f, 0x40, 0x83, 0x59, 0xbf, 0x54, 0xf2, 0x8e,
0xd2, 0x63, 0x62, 0x81, 0xc4, 0xc3, 0x30, 0x8b, 0xac, 0x59, 0xa0, 0x35, 0x68, 0x8b, 0x81, 0x02, 0x8a, 0x11, 0x32, 0x63, 0x72, 0x83, 0x64, 0x61, 0x98, 0x7b, 0xd6, 0x6e, 0xd0, 0x06, 0xf4, 0xe5,
0xa6, 0xf5, 0x1b, 0x58, 0x7b, 0x1e, 0x8e, 0x48, 0x88, 0xf7, 0x4e, 0x4e, 0x9f, 0xe1, 0x34, 0x13, 0x40, 0x09, 0xd3, 0xf9, 0x0d, 0x6c, 0x3c, 0x8d, 0x27, 0x24, 0xc6, 0xbb, 0x87, 0xc7, 0x4f, 0x70,
0x20, 0xa8, 0x8a, 0x6b, 0x5e, 0x2a, 0x5a, 0xb6, 0xe5, 0xbf, 0x38, 0x1a, 0xe1, 0x99, 0xe3, 0x45, 0x16, 0x09, 0x10, 0xd4, 0xe5, 0x33, 0xaf, 0x16, 0x6a, 0xba, 0xea, 0x5f, 0x5e, 0x8d, 0xf8, 0xc4,
0x09, 0xd3, 0x2d, 0x8c, 0xc5, 0xf0, 0x6c, 0x2f, 0x4a, 0x18, 0x7a, 0x07, 0xc4, 0x75, 0xe3, 0xd0, 0x0b, 0x92, 0x94, 0x9b, 0x16, 0x46, 0x23, 0x3e, 0xd9, 0x4d, 0x52, 0x8e, 0x5e, 0x02, 0xf9, 0xdc,
0x70, 0x34, 0x96, 0xe7, 0x63, 0xd9, 0x5e, 0xf2, 0xa2, 0xe4, 0x79, 0x38, 0x1a, 0x5b, 0x3f, 0x96, 0x78, 0x34, 0x9e, 0x4c, 0xd5, 0xfd, 0x68, 0xba, 0xab, 0x41, 0x92, 0x3e, 0x8d, 0x27, 0x53, 0xe7,
0x8f, 0x36, 0x8c, 0x7d, 0xdb, 0x0d, 0x7d, 0x1a, 0xec, 0xe3, 0x8b, 0x9c, 0x86, 0xf4, 0x81, 0x60, 0x87, 0xaa, 0x68, 0xc3, 0x38, 0x74, 0xfd, 0x38, 0xa4, 0xd1, 0x23, 0x7c, 0x51, 0x58, 0x21, 0x2b,
0xf2, 0xc0, 0x77, 0x25, 0x68, 0x3c, 0x1d, 0xe0, 0x90, 0xef, 0x63, 0xee, 0x92, 0x91, 0x7c, 0x04, 0x10, 0x6c, 0x1c, 0xf8, 0xba, 0x02, 0x9d, 0x07, 0x63, 0x1c, 0x8b, 0x47, 0x58, 0xf8, 0x64, 0xa2,
0x5c, 0xe0, 0x98, 0x11, 0x1a, 0xea, 0x03, 0x63, 0x48, 0xf1, 0x86, 0x23, 0x21, 0xe1, 0x8e, 0xef, 0x8a, 0x80, 0x0b, 0xcc, 0x38, 0xa1, 0xb1, 0xb9, 0x30, 0x96, 0x94, 0x35, 0x1c, 0x89, 0x89, 0xf0,
0xe2, 0x80, 0x86, 0x12, 0x65, 0xd9, 0x06, 0xc1, 0xda, 0x97, 0x1c, 0xf4, 0x00, 0x5a, 0xaa, 0xc5, 0x42, 0x1f, 0x47, 0x34, 0x56, 0x28, 0x4d, 0x17, 0x24, 0xeb, 0x91, 0xe2, 0xa0, 0x37, 0xa1, 0xa7,
0xe4, 0x0c, 0xdd, 0xd0, 0x1f, 0xe1, 0xd8, 0x3c, 0xb9, 0x57, 0x14, 0xfb, 0x48, 0x73, 0xd1, 0x87, 0x5b, 0x4c, 0xde, 0x99, 0x1f, 0x87, 0x13, 0xcc, 0x6c, 0xc9, 0xbd, 0xa6, 0xd9, 0xfb, 0x86, 0x8b,
0xb0, 0xaa, 0x0f, 0x52, 0x26, 0x59, 0x95, 0x92, 0x2d, 0xcd, 0x2f, 0x88, 0x26, 0x51, 0x44, 0x63, 0xde, 0x82, 0x75, 0x73, 0x91, 0x72, 0xc9, 0xba, 0x92, 0xec, 0x19, 0x7e, 0x49, 0x34, 0x4d, 0x12,
0xce, 0x1c, 0x86, 0x3d, 0x8f, 0x06, 0x91, 0xae, 0xa0, 0x5b, 0x86, 0xdf, 0x57, 0x6c, 0xb1, 0x84, 0xca, 0x04, 0xf7, 0x38, 0x0e, 0x02, 0x1a, 0x25, 0x26, 0x83, 0xee, 0x59, 0xfe, 0x91, 0x66, 0xcb,
0x87, 0xc2, 0x4f, 0xed, 0x49, 0xb6, 0x84, 0x2b, 0x01, 0x0e, 0x9c, 0xb3, 0x11, 0xf5, 0xce, 0x1d, 0x2d, 0x7c, 0x2c, 0xed, 0x34, 0x96, 0xe4, 0x5b, 0xb8, 0x16, 0xe1, 0xc8, 0x3b, 0x99, 0xd0, 0xe0,
0x91, 0x9a, 0x74, 0x84, 0xc5, 0x1d, 0xbd, 0x2b, 0x98, 0x7d, 0xf2, 0x2d, 0xb6, 0x7e, 0x5f, 0x82, 0xdc, 0x93, 0xa1, 0xc9, 0x78, 0x58, 0xbe, 0xd1, 0x0f, 0x25, 0xf3, 0x88, 0x7c, 0x85, 0x9d, 0xdf,
0xf5, 0xe2, 0x6c, 0x9d, 0x3c, 0xb7, 0x61, 0xbd, 0x38, 0x5d, 0x15, 0xaf, 0xba, 0xca, 0x68, 0xe7, 0x57, 0x60, 0xb3, 0x3c, 0xdb, 0x04, 0xcf, 0x1d, 0xd8, 0x2c, 0x4f, 0xd7, 0xc9, 0xab, 0xc9, 0x32,
0x41, 0x64, 0x79, 0x8a, 0x3e, 0x83, 0xa6, 0xec, 0x25, 0x3a, 0xbe, 0x42, 0x2a, 0xde, 0x7d, 0xf9, 0xfa, 0x45, 0x10, 0x95, 0x9e, 0xa2, 0x0f, 0xa0, 0xab, 0x7a, 0x89, 0x5e, 0xa8, 0x91, 0xca, 0x6f,
0x58, 0xdb, 0x0d, 0x37, 0x47, 0x59, 0x4f, 0xe0, 0x76, 0x1f, 0x73, 0x65, 0x84, 0xcb, 0x75, 0x1d, 0x5f, 0xd1, 0xd7, 0x6e, 0xc7, 0x2f, 0x50, 0xce, 0x7d, 0xb8, 0x79, 0x84, 0x85, 0x56, 0xc2, 0x17,
0xa8, 0x7c, 0x58, 0x85, 0x4a, 0x1f, 0x7b, 0x52, 0x67, 0xc5, 0x16, 0xbf, 0x62, 0x2d, 0x4f, 0x19, 0x26, 0x0f, 0xd4, 0x36, 0xac, 0x43, 0xed, 0x08, 0x07, 0x6a, 0xcd, 0x9a, 0x2b, 0x7f, 0xe5, 0x5e,
0xf6, 0x24, 0x78, 0xc5, 0x96, 0xff, 0xd6, 0x5f, 0x4b, 0xb0, 0xa4, 0x33, 0x95, 0xc8, 0x94, 0x7e, 0x1e, 0x73, 0x1c, 0x28, 0xf0, 0x9a, 0xab, 0xfe, 0x9d, 0xbf, 0x54, 0x60, 0xd5, 0x44, 0x2a, 0x19,
0x4c, 0x2e, 0x70, 0xac, 0x57, 0x51, 0x53, 0xe2, 0x3d, 0xaa, 0xfe, 0x1c, 0x1a, 0x71, 0x42, 0xd3, 0x29, 0x43, 0x46, 0x2e, 0x30, 0x33, 0xbb, 0x68, 0x28, 0x59, 0x8f, 0xea, 0x3f, 0x8f, 0x26, 0x82,
0xfc, 0xd7, 0x54, 0xdc, 0xe7, 0x8a, 0x29, 0xbb, 0x33, 0xb2, 0xf9, 0xa0, 0xeb, 0x7c, 0x4d, 0xc9, 0xd0, 0x2c, 0xfe, 0x75, 0x35, 0xf7, 0xa9, 0x66, 0xaa, 0xee, 0x8c, 0x6a, 0x3e, 0x98, 0x3c, 0xdf,
0x16, 0x0b, 0x13, 0xc7, 0x48, 0xe6, 0xbb, 0x9a, 0xad, 0x29, 0xb1, 0x6b, 0x0c, 0xde, 0x82, 0xc4, 0x50, 0xaa, 0xc5, 0xc2, 0xe5, 0x35, 0x52, 0xf1, 0xae, 0xe5, 0x1a, 0x4a, 0x9e, 0x1a, 0x8b, 0xb7,
0x33, 0xa4, 0xd8, 0x35, 0x01, 0x4d, 0x42, 0xee, 0x44, 0x94, 0x84, 0x5c, 0x27, 0x38, 0x90, 0xac, 0xa2, 0xf0, 0x2c, 0x29, 0x4f, 0x4d, 0x44, 0xd3, 0x58, 0x78, 0x09, 0x25, 0xb1, 0x30, 0x01, 0x0e,
0x13, 0xc1, 0xb1, 0xfe, 0x50, 0x82, 0x45, 0xd5, 0xa1, 0x14, 0x2f, 0x8b, 0xf4, 0x8a, 0x28, 0x13, 0x14, 0xeb, 0x50, 0x72, 0x9c, 0x3f, 0x54, 0xa0, 0xa1, 0x3b, 0x94, 0xb2, 0xb2, 0xc8, 0x9e, 0x88,
0x79, 0xdd, 0x4a, 0x5d, 0xea, 0x5a, 0x90, 0xff, 0xe2, 0x48, 0x5c, 0x04, 0x2a, 0x59, 0x6a, 0xd3, 0x2a, 0x51, 0xcf, 0xad, 0x5a, 0x4b, 0x3f, 0x0b, 0xea, 0x5f, 0x5e, 0x89, 0x8b, 0x48, 0x07, 0x4b,
0x2e, 0x02, 0x91, 0x25, 0x85, 0x67, 0xd9, 0x4d, 0x23, 0xc7, 0x95, 0x89, 0xcd, 0x94, 0x2b, 0xc5, 0xa3, 0xda, 0x45, 0x24, 0xa3, 0xa4, 0xb4, 0x2c, 0x7f, 0x69, 0xd4, 0xb8, 0x56, 0xb1, 0x9b, 0x71,
0xe6, 0x5a, 0x6a, 0xfd, 0x4a, 0x3c, 0xa8, 0xd2, 0xee, 0xdc, 0x2a, 0x54, 0x92, 0xd4, 0x18, 0xf1, 0x95, 0xd8, 0x52, 0x4d, 0x9d, 0x5f, 0xc9, 0x82, 0x2a, 0xeb, 0xce, 0xad, 0x43, 0x2d, 0xcd, 0x94,
0x2b, 0x38, 0x83, 0xf4, 0x8e, 0x12, 0xbf, 0xe8, 0x3e, 0xac, 0xb8, 0xbe, 0x4f, 0xc4, 0x74, 0x77, 0x91, 0xbf, 0x92, 0x33, 0xce, 0xde, 0x28, 0xf9, 0x8b, 0xee, 0xc0, 0x9a, 0x1f, 0x86, 0x44, 0x4e,
0x74, 0x48, 0xfc, 0x74, 0xbf, 0x17, 0xb9, 0x3b, 0x7f, 0x6c, 0xe9, 0x43, 0xa6, 0x4b, 0x7c, 0x74, 0xf7, 0x27, 0x8f, 0x49, 0x98, 0x9d, 0xf7, 0x32, 0xd7, 0xf9, 0x7b, 0x05, 0x7a, 0xbb, 0x34, 0x99,
0x08, 0xad, 0x89, 0x96, 0x31, 0xd2, 0x6f, 0xbe, 0xd9, 0x9d, 0xe4, 0xee, 0x46, 0x4f, 0xb5, 0xa0, 0xfe, 0x8c, 0x4c, 0x70, 0xe1, 0x32, 0x2a, 0x25, 0xf5, 0x02, 0xea, 0x5f, 0x26, 0xab, 0xa7, 0x64,
0x7b, 0xa6, 0x05, 0xdd, 0x3b, 0x08, 0x22, 0x3e, 0x46, 0x07, 0xb0, 0x52, 0x6c, 0xae, 0xa2, 0x3b, 0x82, 0xf5, 0x29, 0xd5, 0x3b, 0xdb, 0x94, 0x0c, 0x79, 0xb8, 0xb2, 0xc1, 0xac, 0xe9, 0xd1, 0xd5,
0xe6, 0xc6, 0x9a, 0xd1, 0x72, 0x9d, 0x0b, 0x73, 0x08, 0xad, 0x89, 0x3e, 0xab, 0xb1, 0x67, 0x76, 0x83, 0x4f, 0x68, 0x88, 0x65, 0x3c, 0x08, 0x09, 0xf3, 0xb2, 0x16, 0x47, 0xd7, 0x5d, 0x0d, 0x09,
0xfb, 0x75, 0x2e, 0xd0, 0x13, 0xa8, 0xe7, 0x1a, 0xab, 0xa8, 0xa3, 0x40, 0xa6, 0x7b, 0xad, 0x73, 0x53, 0x43, 0xc6, 0x90, 0x15, 0xd5, 0x65, 0x2b, 0x1a, 0xd2, 0xd0, 0x1c, 0x69, 0xc8, 0x16, 0x34,
0x01, 0xf6, 0xa0, 0x59, 0xe8, 0x75, 0xa2, 0xae, 0xf6, 0x67, 0x46, 0x03, 0x74, 0x2e, 0xc8, 0x2e, 0xe8, 0xe9, 0x29, 0xc7, 0x42, 0x75, 0x70, 0x6b, 0xae, 0xa1, 0xb2, 0x88, 0xd1, 0xcc, 0x23, 0xc6,
0xd4, 0x73, 0x2d, 0x47, 0x63, 0xc5, 0x74, 0x5f, 0xb3, 0xfb, 0xce, 0x8c, 0x11, 0x7d, 0xee, 0x8f, 0xdd, 0xbf, 0xf6, 0x4c, 0xc4, 0x30, 0xf5, 0x0a, 0x7a, 0x0c, 0xbd, 0x99, 0xfe, 0x37, 0x32, 0x05,
0xa0, 0x59, 0x68, 0x10, 0x1a, 0x43, 0x66, 0x35, 0x27, 0xbb, 0x77, 0x66, 0x8e, 0x69, 0xa4, 0x43, 0xec, 0xe2, 0xb6, 0xf8, 0x70, 0x6b, 0xa4, 0xfb, 0xe9, 0x23, 0xdb, 0x4f, 0x1f, 0xed, 0x45, 0x89,
0x68, 0x4d, 0xb4, 0x0b, 0x4d, 0x70, 0x67, 0x77, 0x11, 0xe7, 0xba, 0xf5, 0xa5, 0x5c, 0xec, 0x5c, 0x98, 0xa2, 0x3d, 0x58, 0x2b, 0x77, 0x8a, 0xd1, 0x2d, 0xfb, 0xfc, 0x2e, 0xe8, 0x1f, 0x2f, 0x85,
0x7d, 0x9c, 0x5b, 0xec, 0xe9, 0xe6, 0x60, 0xf7, 0xdd, 0xd9, 0x83, 0xda, 0xaa, 0x03, 0x58, 0x29, 0x79, 0x0c, 0xbd, 0x99, 0xa6, 0xb1, 0xd5, 0x67, 0x71, 0x2f, 0x79, 0x29, 0xd0, 0x7d, 0x68, 0x17,
0xf6, 0x05, 0x0d, 0xd8, 0xcc, 0x6e, 0xe1, 0xd5, 0x3b, 0xa7, 0xd0, 0x22, 0xcc, 0x76, 0xce, 0xac, 0xba, 0xc4, 0x68, 0xa0, 0x41, 0xe6, 0x1b, 0xc7, 0x4b, 0x01, 0x76, 0xa1, 0x5b, 0x6a, 0xdc, 0xa2,
0xce, 0xe1, 0x5c, 0xa0, 0xa7, 0x00, 0xba, 0x8c, 0xf6, 0x49, 0x98, 0x2e, 0xd9, 0x54, 0xf9, 0x9e, 0xa1, 0xb1, 0x67, 0x41, 0x37, 0x77, 0x29, 0xc8, 0x43, 0x68, 0x17, 0xfa, 0xa7, 0x56, 0x8b, 0xf9,
0x2e, 0xd9, 0x8c, 0x92, 0xfb, 0x09, 0x80, 0xaa, 0x7e, 0x7d, 0x9a, 0x70, 0x74, 0xdb, 0x98, 0x31, 0x26, 0xed, 0xf0, 0xa5, 0x05, 0x23, 0x26, 0x88, 0xed, 0x43, 0xb7, 0xd4, 0xed, 0xb4, 0x8a, 0x2c,
0x51, 0x72, 0x77, 0x3b, 0xd3, 0x03, 0x53, 0x00, 0x38, 0x8e, 0xaf, 0x03, 0xf0, 0x05, 0x40, 0x56, 0xea, 0xb4, 0x0e, 0x6f, 0x2d, 0x1c, 0x33, 0x48, 0x8f, 0xa1, 0x37, 0xd3, 0xfb, 0xb4, 0xce, 0x5d,
0x55, 0x1b, 0x80, 0xa9, 0x3a, 0xfb, 0x8a, 0x18, 0x34, 0xf2, 0x35, 0x34, 0xd2, 0xbe, 0xce, 0xa8, 0xdc, 0x12, 0x5d, 0x6a, 0xd6, 0x27, 0x6a, 0xb3, 0x0b, 0xc9, 0x7e, 0x61, 0xb3, 0xe7, 0x3b, 0x9d,
0xab, 0xe7, 0x42, 0x3c, 0x86, 0x46, 0xbe, 0xb0, 0x32, 0x10, 0x33, 0x8a, 0xad, 0xee, 0x54, 0x3d, 0xc3, 0x97, 0x17, 0x0f, 0x1a, 0xad, 0xf6, 0x60, 0xad, 0xdc, 0xe4, 0xb4, 0x60, 0x0b, 0x5b, 0x9f,
0x84, 0x9e, 0x9a, 0x9d, 0x9a, 0xb1, 0x0a, 0x3b, 0xf5, 0xfb, 0x41, 0x4c, 0x54, 0x64, 0xc5, 0x4c, 0x97, 0x9f, 0x9c, 0x52, 0xbf, 0x33, 0x3f, 0x39, 0x8b, 0xda, 0xa0, 0x4b, 0x81, 0x1e, 0x00, 0x98,
0xf2, 0x3d, 0x20, 0x3e, 0x83, 0x46, 0xbe, 0x14, 0x33, 0x2e, 0xcc, 0x28, 0xcf, 0xba, 0x85, 0x72, 0x9a, 0x20, 0x24, 0x71, 0xb6, 0x65, 0x73, 0xb5, 0x48, 0xb6, 0x65, 0x0b, 0xea, 0x87, 0xfb, 0x00,
0x0c, 0x3d, 0x81, 0x95, 0x62, 0x19, 0x86, 0x72, 0xe7, 0x72, 0xaa, 0x38, 0xeb, 0xea, 0xb7, 0x72, 0x3a, 0x95, 0x0f, 0x69, 0x2a, 0xd0, 0x4d, 0xab, 0xc6, 0x4c, 0xfd, 0x30, 0x1c, 0xcc, 0x0f, 0xcc,
0x4e, 0xfc, 0x21, 0x40, 0x56, 0xae, 0x99, 0xe5, 0x9b, 0x2a, 0xe0, 0x26, 0xb4, 0xee, 0x41, 0xb3, 0x01, 0x60, 0xc6, 0xae, 0x02, 0xf0, 0x31, 0x40, 0x5e, 0x22, 0x58, 0x80, 0xb9, 0xa2, 0xe1, 0x12,
0xf0, 0xf4, 0x30, 0x89, 0x62, 0xd6, 0x7b, 0xe4, 0xaa, 0x3c, 0x5e, 0x2c, 0xf1, 0x8d, 0xe9, 0x33, 0x1f, 0x74, 0x8a, 0x05, 0x01, 0x32, 0xb6, 0x2e, 0x28, 0x12, 0x96, 0x42, 0xdc, 0x83, 0x4e, 0x31,
0x0b, 0xff, 0xab, 0x36, 0x50, 0xbe, 0xb4, 0x34, 0xa1, 0x9b, 0x51, 0x6e, 0xbe, 0xe5, 0x40, 0xe7, 0x4b, 0xb4, 0x10, 0x0b, 0x32, 0xc7, 0xe1, 0x5c, 0x72, 0x87, 0x1e, 0xd8, 0x93, 0x9a, 0xb3, 0x4a,
0xcb, 0xc7, 0xdc, 0x81, 0x9e, 0x51, 0x55, 0xce, 0x05, 0x3a, 0x82, 0xd6, 0xa1, 0x29, 0x67, 0x74, 0x27, 0xf5, 0xdb, 0x41, 0xcc, 0xa4, 0x97, 0xe5, 0x48, 0xf2, 0x2d, 0x20, 0x3e, 0x80, 0x4e, 0x31,
0x6d, 0xa9, 0xcd, 0x99, 0x51, 0xa5, 0x75, 0xbb, 0xb3, 0x86, 0xf4, 0xa9, 0x3a, 0x86, 0xd5, 0xc9, 0xaf, 0xb4, 0x26, 0x2c, 0xc8, 0x35, 0x87, 0xa5, 0xdc, 0x12, 0xdd, 0x87, 0xb5, 0x72, 0x4e, 0x89,
0xc2, 0x08, 0xbd, 0xa7, 0x93, 0xdb, 0xec, 0x82, 0x69, 0x9e, 0x51, 0xbb, 0x8d, 0xef, 0xde, 0xdc, 0x0a, 0xf7, 0x72, 0x2e, 0xd3, 0x1c, 0x9a, 0xc2, 0xbf, 0x20, 0xfe, 0x1e, 0x40, 0x9e, 0x7b, 0xda,
0x2d, 0xfd, 0xfd, 0xcd, 0xdd, 0xd2, 0xbf, 0xde, 0xdc, 0x2d, 0x9d, 0x2d, 0xca, 0xd1, 0x87, 0xff, 0xed, 0x9b, 0xcb, 0x46, 0x67, 0x56, 0xdd, 0x85, 0x6e, 0xa9, 0x8e, 0xb2, 0x81, 0x62, 0x51, 0x71,
0x09, 0x00, 0x00, 0xff, 0xff, 0x0c, 0x58, 0x87, 0x08, 0x36, 0x1e, 0x00, 0x00, 0x75, 0x59, 0x1c, 0x2f, 0xd7, 0x2b, 0x56, 0xf5, 0x85, 0x55, 0xcc, 0x65, 0x07, 0xa8, 0x98, 0x27,
0x5b, 0xd7, 0x2d, 0xc8, 0x9d, 0x5f, 0x70, 0xa1, 0x8b, 0xb9, 0x70, 0xe1, 0x42, 0x2f, 0x48, 0x91,
0x97, 0x02, 0xed, 0x43, 0xef, 0xb1, 0xcd, 0xcd, 0x4c, 0xa2, 0x6c, 0xd4, 0x59, 0x90, 0x72, 0x0e,
0x87, 0x8b, 0x86, 0xcc, 0xad, 0x3a, 0x80, 0xf5, 0xd9, 0x2c, 0x0f, 0xbd, 0x62, 0x82, 0xdb, 0xe2,
0xec, 0x6f, 0xa9, 0x52, 0x3f, 0x81, 0xa6, 0xcd, 0x2a, 0x90, 0x69, 0x9b, 0xcd, 0x64, 0x19, 0xcb,
0xa6, 0x3e, 0xec, 0x7c, 0xfd, 0xcd, 0xab, 0x95, 0x7f, 0x7c, 0xf3, 0x6a, 0xe5, 0xdf, 0xdf, 0xbc,
0x5a, 0x39, 0x69, 0xa8, 0xd1, 0xf7, 0xfe, 0x1b, 0x00, 0x00, 0xff, 0xff, 0x44, 0x3b, 0xc9, 0x9d,
0x3e, 0x1f, 0x00, 0x00,
} }

View File

@ -250,4 +250,7 @@ type agent interface {
// setGuestDateTime asks the agent to set guest time to the provided one // setGuestDateTime asks the agent to set guest time to the provided one
setGuestDateTime(time.Time) error setGuestDateTime(time.Time) error
// copyFile copies file from host to container's rootfs
copyFile(src, dst string) error
} }

View File

@ -9,6 +9,7 @@ const (
blockDeviceSupport = 1 << iota blockDeviceSupport = 1 << iota
blockDeviceHotplugSupport blockDeviceHotplugSupport
multiQueueSupport multiQueueSupport
fsSharingUnsupported
) )
type capabilities struct { type capabilities struct {
@ -47,3 +48,11 @@ func (caps *capabilities) isMultiQueueSupported() bool {
func (caps *capabilities) setMultiQueueSupport() { func (caps *capabilities) setMultiQueueSupport() {
caps.flags |= multiQueueSupport caps.flags |= multiQueueSupport
} }
func (caps *capabilities) isFsSharingSupported() bool {
return caps.flags&fsSharingUnsupported == 0
}
func (caps *capabilities) setFsSharingUnsupported() {
caps.flags |= fsSharingUnsupported
}

View File

@ -34,3 +34,17 @@ func TestBlockDeviceHotplugCapability(t *testing.T) {
t.Fatal() t.Fatal()
} }
} }
func TestFsSharingCapability(t *testing.T) {
var caps capabilities
if !caps.isFsSharingSupported() {
t.Fatal()
}
caps.setFsSharingUnsupported()
if caps.isFsSharingSupported() {
t.Fatal()
}
}

View File

@ -17,6 +17,7 @@ import (
"time" "time"
"github.com/kata-containers/runtime/virtcontainers/pkg/annotations" "github.com/kata-containers/runtime/virtcontainers/pkg/annotations"
"github.com/kata-containers/runtime/virtcontainers/utils"
specs "github.com/opencontainers/runtime-spec/specs-go" specs "github.com/opencontainers/runtime-spec/specs-go"
opentracing "github.com/opentracing/opentracing-go" opentracing "github.com/opentracing/opentracing-go"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
@ -24,7 +25,6 @@ import (
"github.com/kata-containers/runtime/virtcontainers/device/config" "github.com/kata-containers/runtime/virtcontainers/device/config"
"github.com/kata-containers/runtime/virtcontainers/device/manager" "github.com/kata-containers/runtime/virtcontainers/device/manager"
"github.com/kata-containers/runtime/virtcontainers/utils"
) )
// https://github.com/torvalds/linux/blob/master/include/uapi/linux/major.h // https://github.com/torvalds/linux/blob/master/include/uapi/linux/major.h
@ -431,6 +431,36 @@ func (c *Container) createContainersDirs() error {
return nil return nil
} }
func (c *Container) shareFiles(m Mount, idx int, hostSharedDir, guestSharedDir string) (string, error) {
randBytes, err := utils.GenerateRandomBytes(8)
if err != nil {
return "", err
}
filename := fmt.Sprintf("%s-%s-%s", c.id, hex.EncodeToString(randBytes), filepath.Base(m.Destination))
guestDest := filepath.Join(guestSharedDir, filename)
// copy file to contaier's rootfs if filesystem sharing is not supported, otherwise
// bind mount it in the shared directory.
caps := c.sandbox.hypervisor.capabilities()
if !caps.isFsSharingSupported() {
c.Logger().Debug("filesystem sharing is not supported, files will be copied")
if err := c.sandbox.agent.copyFile(m.Source, guestDest); err != nil {
return "", err
}
} else {
// These mounts are created in the shared dir
mountDest := filepath.Join(hostSharedDir, c.sandbox.id, filename)
if err := bindMount(c.ctx, m.Source, mountDest, false); err != nil {
return "", err
}
// Save HostPath mount value into the mount list of the container.
c.mounts[idx].HostPath = mountDest
}
return guestDest, nil
}
// mountSharedDirMounts handles bind-mounts by bindmounting to the host shared // mountSharedDirMounts handles bind-mounts by bindmounting to the host shared
// directory which is mounted through 9pfs in the VM. // directory which is mounted through 9pfs in the VM.
// It also updates the container mount list with the HostPath info, and store // It also updates the container mount list with the HostPath info, and store
@ -472,22 +502,11 @@ func (c *Container) mountSharedDirMounts(hostSharedDir, guestSharedDir string) (
continue continue
} }
randBytes, err := utils.GenerateRandomBytes(8) guestDest, err := c.shareFiles(m, idx, hostSharedDir, guestSharedDir)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// These mounts are created in the shared dir
filename := fmt.Sprintf("%s-%s-%s", c.id, hex.EncodeToString(randBytes), filepath.Base(m.Destination))
mountDest := filepath.Join(hostSharedDir, c.sandbox.id, filename)
if err := bindMount(c.ctx, m.Source, mountDest, false); err != nil {
return nil, err
}
// Save HostPath mount value into the mount list of the container.
c.mounts[idx].HostPath = mountDest
// Check if mount is readonly, let the agent handle the readonly mount // Check if mount is readonly, let the agent handle the readonly mount
// within the VM. // within the VM.
readonly := false readonly := false
@ -498,7 +517,7 @@ func (c *Container) mountSharedDirMounts(hostSharedDir, guestSharedDir string) (
} }
sharedDirMount := Mount{ sharedDirMount := Mount{
Source: filepath.Join(guestSharedDir, filename), Source: guestDest,
Destination: m.Destination, Destination: m.Destination,
Type: m.Type, Type: m.Type,
Options: m.Options, Options: m.Options,

View File

@ -1005,3 +1005,8 @@ func (h *hyper) setGuestDateTime(time.Time) error {
// hyperstart-agent does not support setGuestDateTime // hyperstart-agent does not support setGuestDateTime
return nil return nil
} }
func (h *hyper) copyFile(src, dst string) error {
// hyperstart-agent does not support copyFile
return nil
}

View File

@ -261,3 +261,11 @@ func TestHyperGetAgentUrl(t *testing.T) {
assert.Nil(err) assert.Nil(err)
assert.Empty(url) assert.Empty(url)
} }
func TestHyperCopyFile(t *testing.T) {
assert := assert.New(t)
h := &hyper{}
err := h.copyFile("", "")
assert.Nil(err)
}

View File

@ -9,6 +9,7 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"regexp" "regexp"
@ -34,6 +35,7 @@ import (
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/vishvananda/netlink" "github.com/vishvananda/netlink"
"golang.org/x/net/context" "golang.org/x/net/context"
"golang.org/x/sys/unix"
golangGrpc "google.golang.org/grpc" golangGrpc "google.golang.org/grpc"
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"
grpcStatus "google.golang.org/grpc/status" grpcStatus "google.golang.org/grpc/status"
@ -63,6 +65,7 @@ var (
shmDir = "shm" shmDir = "shm"
kataEphemeralDevType = "ephemeral" kataEphemeralDevType = "ephemeral"
ephemeralPath = filepath.Join(kataGuestSandboxDir, kataEphemeralDevType) ephemeralPath = filepath.Join(kataGuestSandboxDir, kataEphemeralDevType)
grpcMaxDataSize = int64(1024 * 1024)
) )
// KataAgentConfig is a structure storing information needed // KataAgentConfig is a structure storing information needed
@ -252,7 +255,14 @@ func (k *kataAgent) configure(h hypervisor, id, sharePath string, builtin bool,
k.proxyBuiltIn = true k.proxyBuiltIn = true
} }
// Adding the shared volume. // Neither create shared directory nor add 9p device if hypervisor
// doesn't support filesystem sharing.
caps := h.capabilities()
if !caps.isFsSharingSupported() {
return nil
}
// Create shared directory and add the shared volume if filesystem sharing is supported.
// This volume contains all bind mounted container bundles. // This volume contains all bind mounted container bundles.
sharedVolume := Volume{ sharedVolume := Volume{
MountTag: mountGuest9pTag, MountTag: mountGuest9pTag,
@ -612,23 +622,29 @@ func (k *kataAgent) startSandbox(sandbox *Sandbox) error {
return err return err
} }
sharedDir9pOptions = append(sharedDir9pOptions, fmt.Sprintf("msize=%d", sandbox.config.HypervisorConfig.Msize9p)) storages := []*grpc.Storage{}
caps := sandbox.hypervisor.capabilities()
// We mount the shared directory in a predefined location // append 9p shared volume to storages only if filesystem sharing is supported
// in the guest. if caps.isFsSharingSupported() {
// This is where at least some of the host config files sharedDir9pOptions = append(sharedDir9pOptions, fmt.Sprintf("msize=%d", sandbox.config.HypervisorConfig.Msize9p))
// (resolv.conf, etc...) and potentially all container
// rootfs will reside. // We mount the shared directory in a predefined location
sharedVolume := &grpc.Storage{ // in the guest.
Driver: kata9pDevType, // This is where at least some of the host config files
Source: mountGuest9pTag, // (resolv.conf, etc...) and potentially all container
MountPoint: kataGuestSharedDir, // rootfs will reside.
Fstype: type9pFs, sharedVolume := &grpc.Storage{
Options: sharedDir9pOptions, Driver: kata9pDevType,
Source: mountGuest9pTag,
MountPoint: kataGuestSharedDir,
Fstype: type9pFs,
Options: sharedDir9pOptions,
}
storages = append(storages, sharedVolume)
} }
storages := []*grpc.Storage{sharedVolume}
if sandbox.shmSize > 0 { if sandbox.shmSize > 0 {
path := filepath.Join(kataGuestSandboxDir, shmDir) path := filepath.Join(kataGuestSandboxDir, shmDir)
shmSizeOption := fmt.Sprintf("size=%d", sandbox.shmSize) shmSizeOption := fmt.Sprintf("size=%d", sandbox.shmSize)
@ -1490,6 +1506,9 @@ func (k *kataAgent) installReqFunc(c *kataclient.AgentClient) {
k.reqHandlers["grpc.GuestDetailsRequest"] = func(ctx context.Context, req interface{}, opts ...golangGrpc.CallOption) (interface{}, error) { k.reqHandlers["grpc.GuestDetailsRequest"] = func(ctx context.Context, req interface{}, opts ...golangGrpc.CallOption) (interface{}, error) {
return k.client.GetGuestDetails(ctx, req.(*grpc.GuestDetailsRequest), opts...) 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) { k.reqHandlers["grpc.SetGuestDateTimeRequest"] = func(ctx context.Context, req interface{}, opts ...golangGrpc.CallOption) (interface{}, error) {
return k.client.SetGuestDateTime(ctx, req.(*grpc.SetGuestDateTimeRequest), opts...) return k.client.SetGuestDateTime(ctx, req.(*grpc.SetGuestDateTimeRequest), opts...)
} }
@ -1708,3 +1727,56 @@ func (k *kataAgent) convertToRoutes(aRoutes []*aTypes.Route) (routes []*types.Ro
return routes 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
}

View File

@ -247,6 +247,10 @@ func (p *gRPCProxy) SetGuestDateTime(ctx context.Context, req *pb.SetGuestDateTi
return &gpb.Empty{}, nil 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{}) { func gRPCRegister(s *grpc.Server, srv interface{}) {
switch g := srv.(type) { switch g := srv.(type) {
case *gRPCProxy: case *gRPCProxy:
@ -844,3 +848,55 @@ func TestKataGetAgentUrl(t *testing.T) {
assert.NotEmpty(url) 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)
}

View File

@ -209,3 +209,8 @@ func (n *noopAgent) getGuestDetails(*grpc.GuestDetailsRequest) (*grpc.GuestDetai
func (n *noopAgent) setGuestDateTime(time.Time) error { func (n *noopAgent) setGuestDateTime(time.Time) error {
return nil return nil
} }
// copyFile is the Noop agent copy file. It does nothing.
func (n *noopAgent) copyFile(src, dst string) error {
return nil
}

View File

@ -272,3 +272,11 @@ func TestNoopGetAgentUrl(t *testing.T) {
assert.Nil(err) assert.Nil(err)
assert.Empty(url) assert.Empty(url)
} }
func TestNoopCopyFile(t *testing.T) {
assert := assert.New(t)
n := &noopAgent{}
err := n.copyFile("", "")
assert.Nil(err)
}