aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/seaweedfs-csi-driver/Dockerfile.dev6
-rw-r--r--deploy/nomad/example-seaweedfs-volume.hcl6
-rw-r--r--pkg/driver/controllerserver.go35
3 files changed, 41 insertions, 6 deletions
diff --git a/cmd/seaweedfs-csi-driver/Dockerfile.dev b/cmd/seaweedfs-csi-driver/Dockerfile.dev
index 6daecb1..8e758a6 100644
--- a/cmd/seaweedfs-csi-driver/Dockerfile.dev
+++ b/cmd/seaweedfs-csi-driver/Dockerfile.dev
@@ -6,11 +6,15 @@ RUN mkdir -p /go/src/github.com/seaweedfs/
RUN git clone https://github.com/seaweedfs/seaweedfs /go/src/github.com/seaweedfs/seaweedfs
RUN cd /go/src/github.com/seaweedfs/seaweedfs/weed && go install
+WORKDIR /go/src/github.com/seaweedfs/seaweedfs-csi-driver
+COPY . .
+RUN cd /go/src/github.com/seaweedfs/seaweedfs-csi-driver && go build -ldflags="-s -w" -o /seaweedfs-csi-driver ./cmd/seaweedfs-csi-driver/main.go
+
FROM alpine AS final
RUN apk add fuse
LABEL author="Chris Lu"
COPY --from=builder /go/bin/weed /usr/bin/
-COPY ./_output/seaweedfs-csi-driver /seaweedfs-csi-driver
+COPY --from=builder /seaweedfs-csi-driver /
RUN chmod +x /seaweedfs-csi-driver
ENTRYPOINT ["/seaweedfs-csi-driver"]
diff --git a/deploy/nomad/example-seaweedfs-volume.hcl b/deploy/nomad/example-seaweedfs-volume.hcl
index 3a5fb66..145dd8b 100644
--- a/deploy/nomad/example-seaweedfs-volume.hcl
+++ b/deploy/nomad/example-seaweedfs-volume.hcl
@@ -1,4 +1,10 @@
+# id - Nomad internal ID. It is not sent to the CSI plugin but is used by Nomad for `per_alloc`
+# volume configurations, etc.
id = "example-seaweedfs-volume"
+# name - the name sent to the CSI plugin as an idempotency key and suggested volume ID. The CSI
+# spec requires the calling Container Orchestrator to respect the actual volumeId returned by the
+# CSI plugin. Nomad does this, storing it as the volume's ExternalID and using it in subsequent
+# calls to the controller and node.
name = "example-seaweedfs-volume"
type = "csi"
plugin_id = "seaweedfs"
diff --git a/pkg/driver/controllerserver.go b/pkg/driver/controllerserver.go
index 1bd2169..03d5920 100644
--- a/pkg/driver/controllerserver.go
+++ b/pkg/driver/controllerserver.go
@@ -6,15 +6,19 @@ import (
"encoding/hex"
"fmt"
"io"
+ "regexp"
"strings"
"github.com/container-storage-interface/spec/lib/go/csi"
"github.com/seaweedfs/seaweedfs/weed/glog"
"github.com/seaweedfs/seaweedfs/weed/pb/filer_pb"
+ "github.com/seaweedfs/seaweedfs/weed/s3api/s3bucket"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
+var unsafeVolumeIdChars = regexp.MustCompile(`[^-.a-zA-Z0-9]`)
+
type ControllerServer struct {
csi.UnimplementedControllerServer
@@ -26,17 +30,18 @@ var _ = csi.ControllerServer(&ControllerServer{})
func (cs *ControllerServer) CreateVolume(ctx context.Context, req *csi.CreateVolumeRequest) (*csi.CreateVolumeResponse, error) {
glog.Infof("create volume req: %v", req.GetName())
- volumeId := sanitizeVolumeId(req.GetName())
+ // Check arguments
+ suggestedVolumeId := req.GetName()
+ if suggestedVolumeId == "" {
+ return nil, status.Error(codes.InvalidArgument, "Name missing in request")
+ }
+ volumeId := sanitizeVolumeId(suggestedVolumeId)
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 volumeId == "" {
- 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")
}
@@ -189,11 +194,31 @@ func (cs *ControllerServer) ControllerExpandVolume(ctx context.Context, req *csi
func sanitizeVolumeId(volumeId string) string {
volumeId = strings.ToLower(volumeId)
+ // NOTE: leave original length-only logic to ensure backward compatibility with volumes
+ // that happened to work because their suggested volumeId was too long
if len(volumeId) > 63 {
h := sha1.New()
io.WriteString(h, volumeId)
volumeId = hex.EncodeToString(h.Sum(nil))
}
+
+ // check for a valid s3 bucket name according to the rules the filer uses
+ if s3bucket.VerifyS3BucketName(volumeId) != nil {
+ // The suggested volumeId can't be used directly. Use it to generate a new one
+ // that is compatible with our filer's name restrictions.
+ // generate a 40 hexidecimal character SHA1 hash to avoid name collisions
+ h := sha1.New()
+ io.WriteString(h, volumeId)
+ // hexidecimal encoding of sha1 is 40 characters long
+ hexhash := hex.EncodeToString(h.Sum(nil))
+ sanitized := unsafeVolumeIdChars.ReplaceAllString(volumeId, "-")
+ // 21 here is 62 - 40 characters for the hash - 1 more for the "-" we use join
+ // the sanitized ID to the hash
+ if len(sanitized) > 21 {
+ sanitized = sanitized[0:21]
+ }
+ volumeId = fmt.Sprintf("%s.%s", sanitized, hexhash)
+ }
return volumeId
}