This moves both the Mount type and mountinfo into a single mount package. This also opens up the root of the repo to hold the containerd client implementation. Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
		
			
				
	
	
		
			205 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			205 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package snapshot
 | 
						|
 | 
						|
import (
 | 
						|
	gocontext "context"
 | 
						|
 | 
						|
	snapshotapi "github.com/containerd/containerd/api/services/snapshot"
 | 
						|
	mounttypes "github.com/containerd/containerd/api/types/mount"
 | 
						|
	"github.com/containerd/containerd/log"
 | 
						|
	"github.com/containerd/containerd/mount"
 | 
						|
	"github.com/containerd/containerd/plugin"
 | 
						|
	"github.com/containerd/containerd/snapshot"
 | 
						|
	protoempty "github.com/golang/protobuf/ptypes/empty"
 | 
						|
	"golang.org/x/net/context"
 | 
						|
	"google.golang.org/grpc"
 | 
						|
	"google.golang.org/grpc/codes"
 | 
						|
)
 | 
						|
 | 
						|
func init() {
 | 
						|
	plugin.Register("snapshots-grpc", &plugin.Registration{
 | 
						|
		Type: plugin.GRPCPlugin,
 | 
						|
		Init: func(ic *plugin.InitContext) (interface{}, error) {
 | 
						|
			return newService(ic.Snapshotter)
 | 
						|
		},
 | 
						|
	})
 | 
						|
}
 | 
						|
 | 
						|
var empty = &protoempty.Empty{}
 | 
						|
 | 
						|
type service struct {
 | 
						|
	snapshotter snapshot.Snapshotter
 | 
						|
}
 | 
						|
 | 
						|
func newService(snapshotter snapshot.Snapshotter) (*service, error) {
 | 
						|
	return &service{
 | 
						|
		snapshotter: snapshotter,
 | 
						|
	}, nil
 | 
						|
}
 | 
						|
 | 
						|
func (s *service) Register(gs *grpc.Server) error {
 | 
						|
	snapshotapi.RegisterSnapshotServer(gs, s)
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func (s *service) Prepare(ctx context.Context, pr *snapshotapi.PrepareRequest) (*snapshotapi.MountsResponse, error) {
 | 
						|
	log.G(ctx).WithField("parent", pr.Parent).WithField("key", pr.Key).Debugf("Preparing snapshot")
 | 
						|
	// TODO: Apply namespace
 | 
						|
	// TODO: Lookup snapshot id from metadata store
 | 
						|
	mounts, err := s.snapshotter.Prepare(ctx, pr.Key, pr.Parent)
 | 
						|
	if err != nil {
 | 
						|
		return nil, grpcError(err)
 | 
						|
	}
 | 
						|
	return fromMounts(mounts), nil
 | 
						|
}
 | 
						|
 | 
						|
func (s *service) View(ctx context.Context, pr *snapshotapi.PrepareRequest) (*snapshotapi.MountsResponse, error) {
 | 
						|
	log.G(ctx).WithField("parent", pr.Parent).WithField("key", pr.Key).Debugf("Preparing view snapshot")
 | 
						|
	// TODO: Apply namespace
 | 
						|
	// TODO: Lookup snapshot id from metadata store
 | 
						|
	mounts, err := s.snapshotter.View(ctx, pr.Key, pr.Parent)
 | 
						|
	if err != nil {
 | 
						|
		return nil, grpcError(err)
 | 
						|
	}
 | 
						|
	return fromMounts(mounts), nil
 | 
						|
}
 | 
						|
 | 
						|
func (s *service) Mounts(ctx context.Context, mr *snapshotapi.MountsRequest) (*snapshotapi.MountsResponse, error) {
 | 
						|
	log.G(ctx).WithField("key", mr.Key).Debugf("Getting snapshot mounts")
 | 
						|
	// TODO: Apply namespace
 | 
						|
	// TODO: Lookup snapshot id from metadata store
 | 
						|
	mounts, err := s.snapshotter.Mounts(ctx, mr.Key)
 | 
						|
	if err != nil {
 | 
						|
		return nil, grpcError(err)
 | 
						|
	}
 | 
						|
	return fromMounts(mounts), nil
 | 
						|
}
 | 
						|
 | 
						|
func (s *service) Commit(ctx context.Context, cr *snapshotapi.CommitRequest) (*protoempty.Empty, error) {
 | 
						|
	log.G(ctx).WithField("key", cr.Key).WithField("name", cr.Name).Debugf("Committing snapshot")
 | 
						|
	// TODO: Apply namespace
 | 
						|
	// TODO: Lookup snapshot id from metadata store
 | 
						|
	if err := s.snapshotter.Commit(ctx, cr.Name, cr.Key); err != nil {
 | 
						|
		return nil, grpcError(err)
 | 
						|
	}
 | 
						|
	return empty, nil
 | 
						|
}
 | 
						|
 | 
						|
func (s *service) Remove(ctx context.Context, rr *snapshotapi.RemoveRequest) (*protoempty.Empty, error) {
 | 
						|
	log.G(ctx).WithField("key", rr.Key).Debugf("Removing snapshot")
 | 
						|
	// TODO: Apply namespace
 | 
						|
	// TODO: Lookup snapshot id from metadata store
 | 
						|
	if err := s.snapshotter.Remove(ctx, rr.Key); err != nil {
 | 
						|
		return nil, grpcError(err)
 | 
						|
	}
 | 
						|
	return empty, nil
 | 
						|
}
 | 
						|
 | 
						|
func (s *service) Stat(ctx context.Context, sr *snapshotapi.StatRequest) (*snapshotapi.StatResponse, error) {
 | 
						|
	log.G(ctx).WithField("key", sr.Key).Debugf("Statting snapshot")
 | 
						|
	// TODO: Apply namespace
 | 
						|
	info, err := s.snapshotter.Stat(ctx, sr.Key)
 | 
						|
	if err != nil {
 | 
						|
		return nil, grpcError(err)
 | 
						|
	}
 | 
						|
 | 
						|
	return &snapshotapi.StatResponse{Info: fromInfo(info)}, nil
 | 
						|
}
 | 
						|
 | 
						|
func (s *service) List(sr *snapshotapi.ListRequest, ss snapshotapi.Snapshot_ListServer) error {
 | 
						|
	// TODO: Apply namespace
 | 
						|
 | 
						|
	var (
 | 
						|
		buffer    []snapshotapi.Info
 | 
						|
		sendBlock = func(block []snapshotapi.Info) error {
 | 
						|
			return ss.Send(&snapshotapi.ListResponse{
 | 
						|
				Info: block,
 | 
						|
			})
 | 
						|
		}
 | 
						|
	)
 | 
						|
	err := s.snapshotter.Walk(ss.Context(), func(ctx gocontext.Context, info snapshot.Info) error {
 | 
						|
		buffer = append(buffer, fromInfo(info))
 | 
						|
 | 
						|
		if len(buffer) >= 100 {
 | 
						|
			if err := sendBlock(buffer); err != nil {
 | 
						|
				return err
 | 
						|
			}
 | 
						|
 | 
						|
			buffer = buffer[:0]
 | 
						|
		}
 | 
						|
 | 
						|
		return nil
 | 
						|
	})
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	if len(buffer) > 0 {
 | 
						|
		// Send remaining infos
 | 
						|
		if err := sendBlock(buffer); err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func (s *service) Usage(ctx context.Context, ur *snapshotapi.UsageRequest) (*snapshotapi.UsageResponse, error) {
 | 
						|
	// TODO: Apply namespace
 | 
						|
	usage, err := s.snapshotter.Usage(ctx, ur.Key)
 | 
						|
	if err != nil {
 | 
						|
		return nil, grpcError(err)
 | 
						|
	}
 | 
						|
 | 
						|
	return fromUsage(usage), nil
 | 
						|
}
 | 
						|
 | 
						|
func grpcError(err error) error {
 | 
						|
	if snapshot.IsNotExist(err) {
 | 
						|
		return grpc.Errorf(codes.NotFound, err.Error())
 | 
						|
	}
 | 
						|
	if snapshot.IsExist(err) {
 | 
						|
		return grpc.Errorf(codes.AlreadyExists, err.Error())
 | 
						|
	}
 | 
						|
	if snapshot.IsNotActive(err) || snapshot.IsNotCommitted(err) {
 | 
						|
		return grpc.Errorf(codes.FailedPrecondition, err.Error())
 | 
						|
	}
 | 
						|
 | 
						|
	return err
 | 
						|
}
 | 
						|
 | 
						|
func fromKind(kind snapshot.Kind) snapshotapi.Kind {
 | 
						|
	if kind == snapshot.KindActive {
 | 
						|
		return snapshotapi.KindActive
 | 
						|
	}
 | 
						|
	return snapshotapi.KindCommitted
 | 
						|
}
 | 
						|
 | 
						|
func fromInfo(info snapshot.Info) snapshotapi.Info {
 | 
						|
	return snapshotapi.Info{
 | 
						|
		Name:     info.Name,
 | 
						|
		Parent:   info.Parent,
 | 
						|
		Kind:     fromKind(info.Kind),
 | 
						|
		Readonly: info.Readonly,
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func fromUsage(usage snapshot.Usage) *snapshotapi.UsageResponse {
 | 
						|
	return &snapshotapi.UsageResponse{
 | 
						|
		Inodes: usage.Inodes,
 | 
						|
		Size_:  usage.Size,
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func fromMounts(mounts []mount.Mount) *snapshotapi.MountsResponse {
 | 
						|
	resp := &snapshotapi.MountsResponse{
 | 
						|
		Mounts: make([]*mounttypes.Mount, len(mounts)),
 | 
						|
	}
 | 
						|
	for i, m := range mounts {
 | 
						|
		resp.Mounts[i] = &mounttypes.Mount{
 | 
						|
			Type:    m.Type,
 | 
						|
			Source:  m.Source,
 | 
						|
			Options: m.Options,
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return resp
 | 
						|
}
 |