Commit 1caf4699 authored by Cyrill Troxler's avatar Cyrill Troxler
Browse files

Implement a metadata file and correct sizing

As the controller does not mount/create the fs we have to store the capacity somewhere so the node knows about it.
parent db0fbf77
Loading
Loading
Loading
Loading
+27 −7
Original line number Diff line number Diff line
@@ -34,50 +34,71 @@ type controllerServer struct {
}

func (cs *controllerServer) CreateVolume(ctx context.Context, req *csi.CreateVolumeRequest) (*csi.CreateVolumeResponse, error) {
	volumeID := req.GetName()

	if err := cs.Driver.ValidateControllerServiceRequest(csi.ControllerServiceCapability_RPC_CREATE_DELETE_VOLUME); err != nil {
		glog.V(3).Infof("invalid create volume req: %v", req)
		return nil, err
	}

	// Check arguments
	if len(req.GetName()) == 0 {
	if len(volumeID) == 0 {
		return nil, status.Error(codes.InvalidArgument, "Name missing in request")
	}
	if req.GetVolumeCapabilities() == nil {
		return nil, status.Error(codes.InvalidArgument, "Volume Capabilities missing in request")
	}

	volumeID := req.GetName()
	capacityBytes := int64(req.GetCapacityRange().GetRequiredBytes())

	glog.V(5).Infof("Got a request to create bucket %s", volumeID)

	exists, err := cs.s3.client.bucketExists(volumeID)
	if err != nil {
		return nil, err
	}
	if !exists {
	if exists {
		var b *bucket
		b, err = cs.s3.client.getBucket(volumeID)
		if err != nil {
			return nil, err
		}
		// Check if volume capacity requested is bigger than the already existing capacity
		if capacityBytes > b.CapacityBytes {
			return nil, status.Error(codes.AlreadyExists, fmt.Sprintf("Volume with the same name: %s but with smaller size already exist", volumeID))
		}
	} else {
		if err = cs.s3.client.createBucket(volumeID); err != nil {
			glog.V(3).Infof("failed to create volume: %v", err)
			return nil, err
		}
	}
	b := &bucket{
		Name:          volumeID,
		CapacityBytes: capacityBytes,
	}
	if err := cs.s3.client.setBucket(b); err != nil {
		return nil, err
	}

	glog.V(4).Infof("create volume %s", volumeID)
	s3Vol := s3Volume{}
	s3Vol.VolName = req.GetName()
	s3Vol.VolName = volumeID
	s3Vol.VolID = volumeID
	return &csi.CreateVolumeResponse{
		Volume: &csi.Volume{
			Id:            volumeID,
			CapacityBytes: 1,
			CapacityBytes: capacityBytes,
			Attributes:    req.GetParameters(),
		},
	}, nil
}

func (cs *controllerServer) DeleteVolume(ctx context.Context, req *csi.DeleteVolumeRequest) (*csi.DeleteVolumeResponse, error) {
	volumeID := req.GetVolumeId()

	// Check arguments
	if len(req.GetVolumeId()) == 0 {
	if len(volumeID) == 0 {
		return nil, status.Error(codes.InvalidArgument, "Volume ID missing in request")
	}

@@ -85,7 +106,6 @@ func (cs *controllerServer) DeleteVolume(ctx context.Context, req *csi.DeleteVol
		glog.V(3).Infof("Invalid delete volume req: %v", req)
		return nil, err
	}
	volumeID := req.VolumeId
	glog.V(4).Infof("Deleting volume %s", volumeID)

	exists, err := cs.s3.client.bucketExists(volumeID)
+2 −2
Original line number Diff line number Diff line
@@ -25,7 +25,7 @@ const (
)

// newMounter returns a new mounter depending on the mounterType parameter
func newMounter(bucket string, cfg *Config) (Mounter, error) {
func newMounter(bucket *bucket, cfg *Config) (Mounter, error) {
	switch cfg.Mounter {
	case s3fsMounterType:
		return newS3fsMounter(bucket, cfg)
@@ -40,7 +40,7 @@ func newMounter(bucket string, cfg *Config) (Mounter, error) {
		return newS3backerMounter(bucket, cfg)

	}
	return nil, fmt.Errorf("Error mounting bucket %s, invalid mounter specified: %s", bucket, cfg.Mounter)
	return nil, fmt.Errorf("Error mounting bucket %s, invalid mounter specified: %s", bucket.Name, cfg.Mounter)
}

func fuseMount(path string, command string, args []string) error {
+4 −4
Original line number Diff line number Diff line
@@ -16,21 +16,21 @@ const (

// Implements Mounter
type goofysMounter struct {
	bucket          string
	bucket          *bucket
	endpoint        string
	region          string
	accessKeyID     string
	secretAccessKey string
}

func newGoofysMounter(bucket string, cfg *Config) (Mounter, error) {
func newGoofysMounter(b *bucket, cfg *Config) (Mounter, error) {
	region := cfg.Region
	// if endpoint is set we need a default region
	if region == "" && cfg.Endpoint != "" {
		region = defaultRegion
	}
	return &goofysMounter{
		bucket:          bucket,
		bucket:          b,
		endpoint:        cfg.Endpoint,
		region:          region,
		accessKeyID:     cfg.AccessKeyID,
@@ -61,7 +61,7 @@ func (goofys *goofysMounter) Mount(source string, target string) error {
	os.Setenv("AWS_ACCESS_KEY_ID", goofys.accessKeyID)
	os.Setenv("AWS_SECRET_ACCESS_KEY", goofys.secretAccessKey)

	_, _, err := goofysApi.Mount(context.Background(), goofys.bucket, goofysCfg)
	_, _, err := goofysApi.Mount(context.Background(), goofys.bucket.Name, goofysCfg)

	if err != nil {
		return fmt.Errorf("Error mounting via goofys: %s", err)
+11 −8
Original line number Diff line number Diff line
@@ -12,12 +12,11 @@ import (

// Implements Mounter
type s3backerMounter struct {
	bucket          string
	bucket          *bucket
	url             string
	region          string
	accessKeyID     string
	secretAccessKey string
	size            int64
}

const (
@@ -26,23 +25,27 @@ const (
	s3backerDevice = "file"
	// blockSize to use in k
	s3backerBlockSize   = "128k"
	s3backerDefaultSize = 1024 * 1024 * 1024 // 1GiB
)

func newS3backerMounter(bucket string, cfg *Config) (Mounter, error) {
func newS3backerMounter(bucket *bucket, cfg *Config) (Mounter, error) {
	// s3backer cannot work with 0 size volumes
	if bucket.CapacityBytes == 0 {
		bucket.CapacityBytes = s3backerDefaultSize
	}
	s3backer := &s3backerMounter{
		bucket:          bucket,
		url:             cfg.Endpoint,
		region:          cfg.Region,
		accessKeyID:     cfg.AccessKeyID,
		secretAccessKey: cfg.SecretAccessKey,
		size:            1024 * 1024 * 1024 * 10,
	}

	return s3backer, s3backer.writePasswd()
}

func (s3backer *s3backerMounter) String() string {
	return s3backer.bucket
	return s3backer.bucket.Name
}

func (s3backer *s3backerMounter) Stage(stageTarget string) error {
@@ -86,9 +89,9 @@ func (s3backer *s3backerMounter) mountInit(path string) error {
		// baseURL must end with /
		fmt.Sprintf("--baseURL=%s/", s3backer.url),
		fmt.Sprintf("--blockSize=%v", s3backerBlockSize),
		fmt.Sprintf("--size=%v", s3backer.size),
		fmt.Sprintf("--size=%v", s3backer.bucket.CapacityBytes),
		"--listBlocks",
		s3backer.bucket,
		s3backer.bucket.Name,
		path,
	}
	if s3backer.region != "" {
+4 −4
Original line number Diff line number Diff line
@@ -7,7 +7,7 @@ import (

// Implements Mounter
type s3fsMounter struct {
	bucket        string
	bucket        *bucket
	url           string
	region        string
	pwFileContent string
@@ -17,9 +17,9 @@ const (
	s3fsCmd = "s3fs"
)

func newS3fsMounter(bucket string, cfg *Config) (Mounter, error) {
func newS3fsMounter(b *bucket, cfg *Config) (Mounter, error) {
	return &s3fsMounter{
		bucket:        bucket,
		bucket:        b,
		url:           cfg.Endpoint,
		region:        cfg.Region,
		pwFileContent: cfg.AccessKeyID + ":" + cfg.SecretAccessKey,
@@ -39,7 +39,7 @@ func (s3fs *s3fsMounter) Mount(source string, target string) error {
		return err
	}
	args := []string{
		fmt.Sprintf("%s", s3fs.bucket),
		fmt.Sprintf("%s", s3fs.bucket.Name),
		fmt.Sprintf("%s", target),
		"-o", "sigv2",
		"-o", "use_path_request_style",
Loading