Skip to content

Commit

Permalink
Add CSI NodeStage
Browse files Browse the repository at this point in the history
  • Loading branch information
fierlion committed Sep 21, 2023
1 parent dd25e3f commit 9fcbe0e
Show file tree
Hide file tree
Showing 897 changed files with 437,586 additions and 50 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ _bin/
/bin
*.iml
cover.out
cover.out.tmp
coverprofile*.out
/amazon-ecs-init*
/BUILDROOT/
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ GOFILES:=$(shell go list -f '{{$$p := .}}{{range $$f := .GoFiles}}{{$$p.Dir}}/{{
.PHONY: gocyclo
gocyclo:
# Run gocyclo over all .go files
gocyclo -over 17 ${GOFILES}
gocyclo -over 40 ${GOFILES}

# same as gofiles above, but without the `-f`
.PHONY: govet
Expand Down
8 changes: 8 additions & 0 deletions ecs-agent/daemonimages/csidriver/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Build csi-driver from the minimal eks base to add required mount utils
# TODO update Dockerfile with arch to build arm and windows

FROM public.ecr.aws/eks-distro-build-tooling/eks-distro-minimal-base-csi-ebs:latest.2 AS linux-amazon
COPY csi-driver /bin/aws-ebs-csi-driver
ENTRYPOINT ["/bin/aws-ebs-csi-driver"]


100 changes: 100 additions & 0 deletions ecs-agent/daemonimages/csidriver/driver/constants.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may
// not use this file except in compliance with the License. A copy of the
// License is located at
//
// http://aws.amazon.com/apache2.0/
//
// or in the "license" file accompanying this file. This file is distributed
// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.

package driver

// constants of keys in VolumeContext
const (
// VolumeAttributePartition represents key for partition config in VolumeContext
// this represents the partition number on a device used to mount
VolumeAttributePartition = "partition"
)

// constants for fstypes
const (
// FSTypeExt2 represents the ext2 filesystem type
FSTypeExt2 = "ext2"
// FSTypeExt3 represents the ext3 filesystem type
FSTypeExt3 = "ext3"
// FSTypeExt4 represents the ext4 filesystem type
FSTypeExt4 = "ext4"
// FSTypeXfs represents the xfs filesystem type
FSTypeXfs = "xfs"
// FSTypeNtfs represents the ntfs filesystem type
FSTypeNtfs = "ntfs"
)

// constants of disk partition suffix
const (
diskPartitionSuffix = ""
nvmeDiskPartitionSuffix = "p"
)

// constants of keys in volume parameters
const (
// BlockSizeKey configures the block size when formatting a volume
BlockSizeKey = "blocksize"

// INodeSizeKey configures the inode size when formatting a volume
INodeSizeKey = "inodesize"

// BytesPerINodeKey configures the `bytes-per-inode` when formatting a volume
BytesPerINodeKey = "bytesperinode"

// NumberOfINodesKey configures the `number-of-inodes` when formatting a volume
NumberOfINodesKey = "numberofinodes"
)

type fileSystemConfig struct {
NotSupportedParams map[string]struct{}
}

// constants of keys in PublishContext
const (
// devicePathKey represents key for device path in PublishContext
// devicePath is the device path where the volume is attached to
DevicePathKey = "devicePath"
)

var (
FileSystemConfigs = map[string]fileSystemConfig{
FSTypeExt2: {
NotSupportedParams: map[string]struct{}{},
},
FSTypeExt3: {
NotSupportedParams: map[string]struct{}{},
},
FSTypeExt4: {
NotSupportedParams: map[string]struct{}{},
},
FSTypeXfs: {
NotSupportedParams: map[string]struct{}{
BytesPerINodeKey: {},
NumberOfINodesKey: {},
},
},
FSTypeNtfs: {
NotSupportedParams: map[string]struct{}{
BlockSizeKey: {},
INodeSizeKey: {},
BytesPerINodeKey: {},
NumberOfINodesKey: {},
},
},
}
)

func (fsConfig fileSystemConfig) isParameterSupported(paramName string) bool {
_, notSupported := fsConfig.NotSupportedParams[paramName]
return !notSupported
}
68 changes: 68 additions & 0 deletions ecs-agent/daemonimages/csidriver/driver/controller.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may
// not use this file except in compliance with the License. A copy of the
// License is located at
//
// http://aws.amazon.com/apache2.0/
//
// or in the "license" file accompanying this file. This file is distributed
// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.

package driver

import (
"strconv"

csi "github.com/container-storage-interface/spec/lib/go/csi"
"k8s.io/klog/v2"
)

var (
// volumeCaps represents how the volume could be accessed.
// It is SINGLE_NODE_WRITER since EBS volume could only be
// attached to a single node at any given time.
volumeCaps = []csi.VolumeCapability_AccessMode{
{
Mode: csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER,
},
}
)

func isValidVolumeCapabilities(volCaps []*csi.VolumeCapability) bool {
hasSupport := func(cap *csi.VolumeCapability) bool {
for _, c := range volumeCaps {
if c.GetMode() == cap.AccessMode.GetMode() {
return true
}
}
return false
}

foundAll := true
for _, c := range volCaps {
if !hasSupport(c) {
foundAll = false
}
}
return foundAll
}

func isValidVolumeContext(volContext map[string]string) bool {
//There could be multiple volume attributes in the volumeContext map
//Validate here case by case
if partition, ok := volContext[VolumeAttributePartition]; ok {
partitionInt, err := strconv.ParseInt(partition, 10, 64)
if err != nil {
klog.ErrorS(err, "failed to parse partition as int", "partition", partition)
return false
}
if partitionInt < 0 {
klog.ErrorS(err, "invalid partition config", "partition", partition)
return false
}
}
return true
}
72 changes: 72 additions & 0 deletions ecs-agent/daemonimages/csidriver/driver/internal/inflight.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may
// not use this file except in compliance with the License. A copy of the
// License is located at
//
// http://aws.amazon.com/apache2.0/
//
// or in the "license" file accompanying this file. This file is distributed
// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.

package internal

import (
"sync"

"k8s.io/klog/v2"
)

// Idempotent is the interface required to manage in flight requests.
type Idempotent interface {
// The CSI data types are generated using a protobuf.
// The generated structures are guaranteed to implement the Stringer interface.
// Example: https://github.com/container-storage-interface/spec/blob/master/lib/go/csi/csi.pb.go#L3508
// We can use the generated string as the key of our internal inflight database of requests.
String() string
}

const (
VolumeOperationAlreadyExistsErrorMsg = "An operation with the given Volume %s already exists"
)

// InFlight is a struct used to manage in flight requests per volumeId.
type InFlight struct {
mux *sync.Mutex
inFlight map[string]bool
}

// NewInFlight instanciates a InFlight structures.
func NewInFlight() *InFlight {
return &InFlight{
mux: &sync.Mutex{},
inFlight: make(map[string]bool),
}
}

// Insert inserts the entry to the current list of inflight request key is volumeId for node and req hash for controller .
// Returns false when the key already exists.
func (db *InFlight) Insert(key string) bool {
db.mux.Lock()
defer db.mux.Unlock()

_, ok := db.inFlight[key]
if ok {
return false
}

db.inFlight[key] = true
return true
}

// Delete removes the entry from the inFlight entries map.
// It doesn't return anything, and will do nothing if the specified key doesn't exist.
func (db *InFlight) Delete(key string) {
db.mux.Lock()
defer db.mux.Unlock()

delete(db.inFlight, key)
klog.V(4).InfoS("Node Service: volume operation finished", "key", key)
}
Loading

0 comments on commit 9fcbe0e

Please sign in to comment.