github.com/projecteru2/core@v0.0.0-20240321043226-06bcc1c23f58/rpc/transform.go (about)

     1  package rpc
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"fmt"
     7  	"time"
     8  
     9  	enginetypes "github.com/projecteru2/core/engine/types"
    10  	"github.com/projecteru2/core/log"
    11  	resourcetypes "github.com/projecteru2/core/resource/types"
    12  	pb "github.com/projecteru2/core/rpc/gen"
    13  	"github.com/projecteru2/core/types"
    14  	"github.com/projecteru2/core/utils"
    15  
    16  	"golang.org/x/net/context"
    17  )
    18  
    19  func toRPCServiceStatus(status types.ServiceStatus) *pb.ServiceStatus {
    20  	return &pb.ServiceStatus{
    21  		Addresses:        status.Addresses,
    22  		IntervalInSecond: int64(status.Interval / time.Second),
    23  	}
    24  }
    25  
    26  func toRPCPod(p *types.Pod) *pb.Pod {
    27  	return &pb.Pod{Name: p.Name, Desc: p.Desc}
    28  }
    29  
    30  func toRPCNetwork(n *enginetypes.Network) *pb.Network {
    31  	return &pb.Network{Name: n.Name, Subnets: n.Subnets}
    32  }
    33  
    34  func toRPCNode(n *types.Node) *pb.Node {
    35  	node := &pb.Node{
    36  		Name:             n.Name,
    37  		Endpoint:         n.Endpoint,
    38  		Podname:          n.Podname,
    39  		Available:        n.Available,
    40  		Labels:           n.Labels,
    41  		Info:             n.NodeInfo,
    42  		Bypass:           n.Bypass,
    43  		Test:             n.Test,
    44  		ResourceCapacity: toRPCResources(n.ResourceInfo.Capacity),
    45  		ResourceUsage:    toRPCResources(n.ResourceInfo.Usage),
    46  	}
    47  	return node
    48  }
    49  
    50  func toRPCResources(v any) string {
    51  	body, _ := json.Marshal(v)
    52  	return string(body)
    53  }
    54  
    55  func toRPCEngine(e *enginetypes.Info) *pb.Engine {
    56  	return &pb.Engine{
    57  		Type: e.Type,
    58  	}
    59  }
    60  
    61  func toRPCNodeResource(nr *types.NodeResourceInfo) *pb.NodeResource {
    62  	return &pb.NodeResource{
    63  		Name:             nr.Name,
    64  		Diffs:            nr.Diffs,
    65  		ResourceCapacity: toRPCResources(nr.Capacity),
    66  		ResourceUsage:    toRPCResources(nr.Usage),
    67  	}
    68  }
    69  
    70  func toRPCBuildImageMessage(b *types.BuildImageMessage) *pb.BuildImageMessage {
    71  	return &pb.BuildImageMessage{
    72  		Id:       b.ID,
    73  		Status:   b.Status,
    74  		Progress: b.Progress,
    75  		Error:    b.Error,
    76  		Stream:   b.Stream,
    77  		ErrorDetail: &pb.ErrorDetail{
    78  			Code:    int64(b.ErrorDetail.Code),
    79  			Message: b.ErrorDetail.Message,
    80  		},
    81  	}
    82  }
    83  
    84  func toCoreListNodesOptions(b *pb.ListNodesOptions) *types.ListNodesOptions {
    85  	return &types.ListNodesOptions{
    86  		Podname:  b.Podname,
    87  		Labels:   b.Labels,
    88  		All:      b.All,
    89  		CallInfo: !b.SkipInfo,
    90  	}
    91  }
    92  
    93  func toCoreCopyOptions(b *pb.CopyOptions) *types.CopyOptions {
    94  	r := &types.CopyOptions{Targets: map[string][]string{}}
    95  	for cid, paths := range b.Targets {
    96  		r.Targets[cid] = []string{}
    97  		r.Targets[cid] = append(r.Targets[cid], paths.Paths...)
    98  	}
    99  	return r
   100  }
   101  
   102  func toCoreSendOptions(b *pb.SendOptions) (*types.SendOptions, error) { //nolint
   103  	files := []types.LinuxFile{}
   104  	for filename, content := range b.Data {
   105  		files = append(files, types.LinuxFile{
   106  			Content:  content,
   107  			Filename: filename,
   108  			UID:      int(b.Owners[filename].GetUid()),
   109  			GID:      int(b.Owners[filename].GetGid()),
   110  			Mode:     b.Modes[filename].GetMode(),
   111  		})
   112  	}
   113  	return &types.SendOptions{
   114  		IDs:   b.IDs,
   115  		Files: files,
   116  	}, nil
   117  }
   118  
   119  func toCoreAddNodeOptions(b *pb.AddNodeOptions) *types.AddNodeOptions {
   120  	r := &types.AddNodeOptions{
   121  		Nodename:  b.Nodename,
   122  		Endpoint:  b.Endpoint,
   123  		Podname:   b.Podname,
   124  		Ca:        b.Ca,
   125  		Cert:      b.Cert,
   126  		Key:       b.Key,
   127  		Labels:    b.Labels,
   128  		Resources: toCoreResources(b.Resources),
   129  		Test:      b.Test,
   130  	}
   131  	return r
   132  }
   133  
   134  func toCoreSetNodeOptions(b *pb.SetNodeOptions) (*types.SetNodeOptions, error) { //nolint
   135  	r := &types.SetNodeOptions{
   136  		Nodename:      b.Nodename,
   137  		Endpoint:      b.Endpoint,
   138  		Ca:            b.Ca,
   139  		Cert:          b.Cert,
   140  		Key:           b.Key,
   141  		WorkloadsDown: b.WorkloadsDown,
   142  		Resources:     toCoreResources(b.Resources),
   143  		Delta:         b.Delta,
   144  		Labels:        b.Labels,
   145  		Bypass:        types.TriOptions(b.Bypass),
   146  	}
   147  	return r, nil
   148  }
   149  
   150  func toCoreBuildOptions(b *pb.BuildImageOptions) (*types.BuildOptions, error) {
   151  	var builds *types.Builds
   152  	if b.GetBuilds() != nil {
   153  		if len(b.GetBuilds().Stages) == 0 {
   154  			return nil, types.ErrNoBuildsInSpec
   155  		}
   156  		builds = &types.Builds{
   157  			Stages: b.GetBuilds().Stages,
   158  		}
   159  		builds.Builds = map[string]*types.Build{}
   160  		for stage, p := range b.GetBuilds().Builds {
   161  			if p == nil {
   162  				return nil, types.ErrNoBuildSpec
   163  			}
   164  			builds.Builds[stage] = &types.Build{
   165  				Base:       p.Base,
   166  				Repo:       p.Repo,
   167  				Version:    p.Version,
   168  				Dir:        p.Dir,
   169  				Submodule:  p.Submodule || false,
   170  				Security:   p.Security || false,
   171  				Commands:   p.Commands,
   172  				Envs:       p.Envs,
   173  				Args:       p.Args,
   174  				Labels:     p.Labels,
   175  				Artifacts:  p.Artifacts,
   176  				Cache:      p.Cache,
   177  				StopSignal: p.StopSignal,
   178  			}
   179  		}
   180  	}
   181  
   182  	var buildMethod types.BuildMethod
   183  	switch b.GetBuildMethod() {
   184  	case pb.BuildImageOptions_SCM:
   185  		buildMethod = types.BuildFromSCM
   186  	case pb.BuildImageOptions_RAW:
   187  		buildMethod = types.BuildFromRaw
   188  	case pb.BuildImageOptions_EXIST:
   189  		buildMethod = types.BuildFromExist
   190  	}
   191  
   192  	return &types.BuildOptions{
   193  		Name:        b.Name,
   194  		User:        b.User,
   195  		UID:         int(b.Uid),
   196  		Tags:        b.Tags,
   197  		BuildMethod: buildMethod,
   198  		Builds:      builds,
   199  		Tar:         bytes.NewReader(b.Tar),
   200  		ExistID:     b.GetExistId(),
   201  		Platform:    b.Platform,
   202  	}, nil
   203  }
   204  
   205  func toCoreReplaceOptions(r *pb.ReplaceOptions) (*types.ReplaceOptions, error) {
   206  	deployOpts, err := toCoreDeployOptions(r.DeployOpt)
   207  	if err != nil {
   208  		return nil, err
   209  	}
   210  
   211  	replaceOpts := &types.ReplaceOptions{
   212  		DeployOptions:  *deployOpts,
   213  		NetworkInherit: r.Networkinherit,
   214  		FilterLabels:   r.FilterLabels,
   215  		Copy:           r.Copy,
   216  		IDs:            r.IDs,
   217  	}
   218  
   219  	return replaceOpts, err
   220  }
   221  
   222  func toCoreDeployOptions(d *pb.DeployOptions) (*types.DeployOptions, error) {
   223  	if d == nil {
   224  		return nil, types.ErrNoDeployOpts
   225  	}
   226  	if d.Entrypoint == nil || d.Entrypoint.Name == "" {
   227  		return nil, types.ErrNoEntryInSpec
   228  	}
   229  
   230  	entrypoint := d.Entrypoint
   231  	entry := &types.Entrypoint{
   232  		Name:       entrypoint.Name,
   233  		Commands:   utils.MakeCommandLineArgs(fmt.Sprintf("%s %s", d.Entrypoint.Command, d.ExtraArgs)),
   234  		Privileged: entrypoint.Privileged,
   235  		Dir:        entrypoint.Dir,
   236  		Publish:    entrypoint.Publish,
   237  		Restart:    entrypoint.Restart,
   238  		Sysctls:    entrypoint.Sysctls,
   239  	}
   240  
   241  	if len(d.Entrypoint.Commands) > 0 {
   242  		entry.Commands = d.Entrypoint.Commands
   243  	}
   244  
   245  	if entrypoint.Log != nil && entrypoint.Log.Type != "" {
   246  		entry.Log = &types.LogConfig{}
   247  		entry.Log.Type = entrypoint.Log.Type
   248  		entry.Log.Config = entrypoint.Log.Config
   249  	}
   250  
   251  	if entrypoint.Healthcheck != nil {
   252  		entry.HealthCheck = &types.HealthCheck{}
   253  		entry.HealthCheck.TCPPorts = entrypoint.Healthcheck.TcpPorts
   254  		entry.HealthCheck.HTTPPort = entrypoint.Healthcheck.HttpPort
   255  		entry.HealthCheck.HTTPURL = entrypoint.Healthcheck.Url
   256  		entry.HealthCheck.HTTPCode = int(entrypoint.Healthcheck.Code)
   257  	}
   258  
   259  	if entrypoint.Hook != nil {
   260  		entry.Hook = &types.Hook{}
   261  		entry.Hook.AfterStart = entrypoint.Hook.AfterStart
   262  		entry.Hook.BeforeStop = entrypoint.Hook.BeforeStop
   263  		entry.Hook.Force = entrypoint.Hook.Force
   264  	}
   265  
   266  	files := []types.LinuxFile{}
   267  	for filename, bs := range d.Data {
   268  		file := types.LinuxFile{
   269  			Content:  bs,
   270  			Filename: filename,
   271  			UID:      int(d.Owners[filename].GetUid()),
   272  			GID:      int(d.Owners[filename].GetGid()),
   273  			Mode:     d.Modes[filename].GetMode(),
   274  		}
   275  		if file.Mode == 0 && file.UID == 0 && file.GID == 0 {
   276  			file.Mode = 0755
   277  		}
   278  		files = append(files, file)
   279  	}
   280  
   281  	nodeFilter := &types.NodeFilter{
   282  		Podname:  d.Podname,
   283  		Includes: d.Nodenames,
   284  		Labels:   d.Nodelabels,
   285  	}
   286  	if d.NodeFilter != nil {
   287  		nodeFilter.Includes = d.NodeFilter.Includes
   288  		nodeFilter.Excludes = d.NodeFilter.Excludes
   289  		nodeFilter.Labels = d.NodeFilter.Labels
   290  	}
   291  
   292  	return &types.DeployOptions{
   293  		Resources:      toCoreResources(d.Resources),
   294  		Name:           d.Name,
   295  		Entrypoint:     entry,
   296  		Podname:        d.Podname,
   297  		NodeFilter:     nodeFilter,
   298  		Image:          d.Image,
   299  		ExtraArgs:      d.ExtraArgs,
   300  		Count:          int(d.Count),
   301  		Env:            d.Env,
   302  		DNS:            d.Dns,
   303  		ExtraHosts:     d.ExtraHosts,
   304  		Networks:       d.Networks,
   305  		User:           d.User,
   306  		Debug:          d.Debug,
   307  		OpenStdin:      d.OpenStdin,
   308  		Labels:         d.Labels,
   309  		DeployStrategy: d.DeployStrategy.String(),
   310  		NodesLimit:     int(d.NodesLimit),
   311  		IgnoreHook:     d.IgnoreHook,
   312  		AfterCreate:    d.AfterCreate,
   313  		RawArgs:        d.RawArgs,
   314  		Files:          files,
   315  		IgnorePull:     d.IgnorePull,
   316  	}, nil
   317  }
   318  
   319  func toRPCCreateWorkloadMessage(c *types.CreateWorkloadMessage) *pb.CreateWorkloadMessage {
   320  	if c == nil {
   321  		return nil
   322  	}
   323  
   324  	msg := &pb.CreateWorkloadMessage{
   325  		Podname:   c.Podname,
   326  		Nodename:  c.Nodename,
   327  		Id:        c.WorkloadID,
   328  		Name:      c.WorkloadName,
   329  		Success:   c.Error == nil,
   330  		Publish:   utils.EncodePublishInfo(c.Publish),
   331  		Hook:      utils.MergeHookOutputs(c.Hook),
   332  		Resources: toRPCResources(c.Resources),
   333  	}
   334  	if c.Error != nil {
   335  		msg.Error = c.Error.Error()
   336  	}
   337  	return msg
   338  }
   339  
   340  func toRPCReplaceWorkloadMessage(r *types.ReplaceWorkloadMessage) *pb.ReplaceWorkloadMessage {
   341  	msg := &pb.ReplaceWorkloadMessage{
   342  		Create: toRPCCreateWorkloadMessage(r.Create),
   343  		Remove: toRPCRemoveWorkloadMessage(r.Remove),
   344  	}
   345  	if r.Error != nil {
   346  		msg.Error = r.Error.Error()
   347  	}
   348  	return msg
   349  }
   350  
   351  func toRPCCacheImageMessage(r *types.CacheImageMessage) *pb.CacheImageMessage {
   352  	return &pb.CacheImageMessage{
   353  		Image:    r.Image,
   354  		Success:  r.Success,
   355  		Nodename: r.Nodename,
   356  		Message:  r.Message,
   357  	}
   358  }
   359  
   360  func toRPCRemoveImageMessage(r *types.RemoveImageMessage) *pb.RemoveImageMessage {
   361  	return &pb.RemoveImageMessage{
   362  		Image:    r.Image,
   363  		Success:  r.Success,
   364  		Messages: r.Messages,
   365  	}
   366  }
   367  
   368  func toRPCControlWorkloadMessage(c *types.ControlWorkloadMessage) *pb.ControlWorkloadMessage {
   369  	r := &pb.ControlWorkloadMessage{
   370  		Id:   c.WorkloadID,
   371  		Hook: utils.MergeHookOutputs(c.Hook),
   372  	}
   373  	if c.Error != nil {
   374  		r.Error = c.Error.Error()
   375  	}
   376  	return r
   377  }
   378  
   379  func toRPCRemoveWorkloadMessage(r *types.RemoveWorkloadMessage) *pb.RemoveWorkloadMessage {
   380  	if r == nil {
   381  		return nil
   382  	}
   383  	return &pb.RemoveWorkloadMessage{
   384  		Id:      r.WorkloadID,
   385  		Success: r.Success,
   386  		Hook:    string(utils.MergeHookOutputs(r.Hook)),
   387  	}
   388  }
   389  
   390  func toRPCDissociateWorkloadMessage(r *types.DissociateWorkloadMessage) *pb.DissociateWorkloadMessage {
   391  	resp := &pb.DissociateWorkloadMessage{
   392  		Id: r.WorkloadID,
   393  	}
   394  	if r.Error != nil {
   395  		resp.Error = r.Error.Error()
   396  	}
   397  	return resp
   398  }
   399  
   400  func toRPCStdStreamType(stdType types.StdStreamType) pb.StdStreamType {
   401  	switch stdType {
   402  	case types.EruError:
   403  		return pb.StdStreamType_ERUERROR
   404  	case types.TypeWorkloadID:
   405  		return pb.StdStreamType_TYPEWORKLOADID
   406  	case types.Stdout:
   407  		return pb.StdStreamType_STDOUT
   408  	default:
   409  		return pb.StdStreamType_STDERR
   410  	}
   411  }
   412  
   413  func toRPCAttachWorkloadMessage(msg *types.AttachWorkloadMessage) *pb.AttachWorkloadMessage {
   414  	return &pb.AttachWorkloadMessage{
   415  		WorkloadId:    msg.WorkloadID,
   416  		Data:          msg.Data,
   417  		StdStreamType: toRPCStdStreamType(msg.StdStreamType),
   418  	}
   419  }
   420  
   421  func toRPCWorkloadStatus(workloadStatus *types.StatusMeta) *pb.WorkloadStatus {
   422  	r := &pb.WorkloadStatus{}
   423  	if workloadStatus != nil {
   424  		r.Id = workloadStatus.ID
   425  		r.Healthy = workloadStatus.Healthy
   426  		r.Running = workloadStatus.Running
   427  		r.Networks = workloadStatus.Networks
   428  		r.Extension = workloadStatus.Extension
   429  	}
   430  	return r
   431  }
   432  
   433  func toRPCWorkloadsStatus(workloadsStatus []*types.StatusMeta) *pb.WorkloadsStatus {
   434  	ret := &pb.WorkloadsStatus{}
   435  	r := []*pb.WorkloadStatus{}
   436  	for _, cs := range workloadsStatus {
   437  		s := toRPCWorkloadStatus(cs)
   438  		if s != nil {
   439  			r = append(r, s)
   440  		}
   441  	}
   442  	ret.Status = r
   443  	return ret
   444  }
   445  
   446  func toRPCWorkloads(ctx context.Context, workloads []*types.Workload, labels map[string]string) *pb.Workloads {
   447  	ret := &pb.Workloads{}
   448  	cs := []*pb.Workload{}
   449  	for _, c := range workloads {
   450  		pWorkload, err := toRPCWorkload(ctx, c)
   451  		if err != nil {
   452  			log.WithFunc("transform.toRPCWorkloads").Error(ctx, err, "trans to pb workload failed")
   453  			continue
   454  		}
   455  		if !utils.LabelsFilter(pWorkload.Labels, labels) {
   456  			continue
   457  		}
   458  		cs = append(cs, pWorkload)
   459  	}
   460  	ret.Workloads = cs
   461  	return ret
   462  }
   463  
   464  func toRPCWorkload(ctx context.Context, c *types.Workload) (*pb.Workload, error) {
   465  	publish := map[string]string{}
   466  	if c.StatusMeta != nil && len(c.StatusMeta.Networks) != 0 {
   467  		meta := utils.DecodeMetaInLabel(ctx, c.Labels)
   468  		publish = utils.EncodePublishInfo(
   469  			utils.MakePublishInfo(c.StatusMeta.Networks, meta.Publish),
   470  		)
   471  	}
   472  
   473  	return &pb.Workload{
   474  		Id:         c.ID,
   475  		Podname:    c.Podname,
   476  		Nodename:   c.Nodename,
   477  		Name:       c.Name,
   478  		Privileged: c.Privileged,
   479  		Publish:    publish,
   480  		Image:      c.Image,
   481  		Labels:     c.Labels,
   482  		Status:     toRPCWorkloadStatus(c.StatusMeta),
   483  		CreateTime: c.CreateTime,
   484  		Resources:  toRPCResources(c.Resources),
   485  		Env:        c.Env,
   486  	}, nil
   487  }
   488  
   489  func toRPCLogStreamMessage(msg *types.LogStreamMessage) *pb.LogStreamMessage {
   490  	r := &pb.LogStreamMessage{
   491  		Id:            msg.ID,
   492  		Data:          msg.Data,
   493  		StdStreamType: toRPCStdStreamType(msg.StdStreamType),
   494  	}
   495  	if msg.Error != nil {
   496  		r.Error = msg.Error.Error()
   497  	}
   498  	return r
   499  }
   500  
   501  func toCoreExecuteWorkloadOptions(b *pb.ExecuteWorkloadOptions) (opts *types.ExecuteWorkloadOptions, err error) { //nolint
   502  	return &types.ExecuteWorkloadOptions{
   503  		WorkloadID: b.WorkloadId,
   504  		Commands:   b.Commands,
   505  		Envs:       b.Envs,
   506  		Workdir:    b.Workdir,
   507  		OpenStdin:  b.OpenStdin,
   508  		ReplCmd:    b.ReplCmd,
   509  	}, nil
   510  }
   511  
   512  func toRPCCapacityMessage(msg *types.CapacityMessage) *pb.CapacityMessage {
   513  	if msg == nil {
   514  		return nil
   515  	}
   516  	caps := map[string]int64{}
   517  	for nodename, capacity := range msg.NodeCapacities {
   518  		caps[nodename] = int64(capacity)
   519  	}
   520  	return &pb.CapacityMessage{
   521  		Total:          int64(msg.Total),
   522  		NodeCapacities: caps,
   523  	}
   524  }
   525  
   526  func toCoreCacheImageOptions(opts *pb.CacheImageOptions) *types.ImageOptions {
   527  	return &types.ImageOptions{
   528  		Podname:   opts.Podname,
   529  		Nodenames: opts.Nodenames,
   530  		Images:    opts.Images,
   531  	}
   532  }
   533  
   534  func toCoreRemoveImageOptions(opts *pb.RemoveImageOptions) *types.ImageOptions {
   535  	return &types.ImageOptions{
   536  		Podname:   opts.Podname,
   537  		Nodenames: opts.Nodenames,
   538  		Images:    opts.Images,
   539  		Prune:     opts.Prune,
   540  	}
   541  }
   542  
   543  func toCoreResources(resources map[string][]byte) resourcetypes.Resources {
   544  	r := resourcetypes.Resources{}
   545  	for k, v := range resources {
   546  		rp := resourcetypes.RawParams{}
   547  		if err := json.Unmarshal(v, &rp); err != nil {
   548  			log.WithFunc("toCoreResources").Errorf(nil, err, "%v", string(v)) // nolint
   549  			continue
   550  		}
   551  		r[k] = rp
   552  	}
   553  	return r
   554  }
   555  
   556  func toRPCListImageMessage(msg *types.ListImageMessage) *pb.ListImageMessage {
   557  	m := &pb.ListImageMessage{
   558  		Images:   []*pb.ImageItem{},
   559  		Nodename: "",
   560  		Err:      "",
   561  	}
   562  	if msg == nil {
   563  		return m
   564  	}
   565  	if msg.Error != nil {
   566  		m.Err = msg.Error.Error()
   567  		return m
   568  	}
   569  
   570  	m.Nodename = msg.Nodename
   571  	for _, image := range msg.Images {
   572  		m.Images = append(m.Images, &pb.ImageItem{
   573  			Id:   image.ID,
   574  			Tags: image.Tags,
   575  		})
   576  	}
   577  
   578  	return m
   579  }
   580  
   581  func toCoreListImageOptions(opts *pb.ListImageOptions) *types.ImageOptions {
   582  	return &types.ImageOptions{
   583  		Podname:   opts.Podname,
   584  		Nodenames: opts.Nodenames,
   585  		Filter:    opts.Filter,
   586  	}
   587  }
   588  
   589  func toSendLargeFileOptions(opts *pb.FileOptions) (*types.SendLargeFileOptions, error) {
   590  	ret := &types.SendLargeFileOptions{
   591  		IDs:   opts.Ids,
   592  		Dst:   opts.Dst,
   593  		Size:  opts.Size,
   594  		Mode:  opts.Mode.Mode,
   595  		UID:   int(opts.Owner.Uid),
   596  		GID:   int(opts.Owner.Gid),
   597  		Chunk: opts.Chunk,
   598  	}
   599  	err := ret.Validate()
   600  	return ret, err
   601  }
   602  
   603  func toSendLargeFileChunks(file types.LinuxFile, ids []string) []*types.SendLargeFileOptions {
   604  	maxChunkSize := types.SendLargeFileChunkSize
   605  	ret := make([]*types.SendLargeFileOptions, 0)
   606  	for idx := 0; idx < len(file.Content); idx += maxChunkSize {
   607  		sendLargeFileOptions := &types.SendLargeFileOptions{
   608  			IDs:  ids,
   609  			Dst:  file.Filename,
   610  			Size: int64(len(file.Content)),
   611  			Mode: file.Mode,
   612  			UID:  file.UID,
   613  			GID:  file.GID,
   614  		}
   615  		if idx+maxChunkSize > len(file.Content) {
   616  			sendLargeFileOptions.Chunk = file.Content[idx:]
   617  		} else {
   618  			sendLargeFileOptions.Chunk = file.Content[idx : idx+maxChunkSize]
   619  		}
   620  		ret = append(ret, sendLargeFileOptions)
   621  	}
   622  	return ret
   623  }
   624  
   625  func toCoreRawEngineOptions(d *pb.RawEngineOptions) (*types.RawEngineOptions, error) {
   626  	ret := &types.RawEngineOptions{
   627  		ID:         d.Id,
   628  		Op:         d.Op,
   629  		Params:     d.Params,
   630  		IgnoreLock: d.IgnoreLock,
   631  	}
   632  	err := ret.Validate()
   633  	return ret, err
   634  }
   635  
   636  func toRPCRawEngineMessage(c *types.RawEngineMessage) *pb.RawEngineMessage {
   637  	r := &pb.RawEngineMessage{
   638  		Id:   c.ID,
   639  		Data: c.Data,
   640  	}
   641  	return r
   642  }