Skip to content

Commit

Permalink
cinder-csi: Add basic support for an encrypted storage class parameter
Browse files Browse the repository at this point in the history
  • Loading branch information
NotTheEvilOne committed Feb 6, 2024
1 parent 64b8130 commit 86b647f
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 19 deletions.
15 changes: 8 additions & 7 deletions docs/cinder-csi-plugin/using-cinder-csi-plugin.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ Implementation of `cinder-csi-plugin` relies on following OpenStack services.
For Driver configuration, parameters must be passed via configuration file specified in `$CLOUD_CONFIG` environment variable.
The following sections are supported in configuration file.

### Global
### Global
For Cinder CSI Plugin to authenticate with OpenStack Keystone, required parameters needs to be passed in `[Global]` section of the file. For all supported parameters, please refer [Global](../openstack-cloud-controller-manager/using-openstack-cloud-controller-manager.md#global) section.

### Block Storage
Expand Down Expand Up @@ -196,7 +196,7 @@ cinder.csi.openstack.org true true false <
mountPath: /etc/cacert
readOnly: true
volumes:
volumes:
....
- name: cacert
hostPath:
Expand Down Expand Up @@ -253,8 +253,9 @@ helm install --namespace kube-system --name cinder-csi ./charts/cinder-csi-plugi
|------------------------- |-----------------------|-----------------|-----------------|
| StorageClass `parameters` | `availability` | `nova` | String. Volume Availability Zone |
| StorageClass `parameters` | `type` | Empty String | String. Name/ID of Volume type. Corresponding volume type should exist in cinder |
| StorageClass `parameters` | `encrypted` | Empty String | String. True if Volume Encryption is requested |
| VolumeSnapshotClass `parameters` | `force-create` | `false` | Enable to support creating snapshot for a volume in in-use status |
| Inline Volume `volumeAttributes` | `capacity` | `1Gi` | volume size for creating inline volumes|
| Inline Volume `volumeAttributes` | `capacity` | `1Gi` | volume size for creating inline volumes|
| Inline Volume `VolumeAttributes` | `type` | Empty String | Name/ID of Volume type. Corresponding volume type should exist in cinder |

## Local Development
Expand All @@ -266,14 +267,14 @@ To build the plugin, run
```
$ export ARCH=amd64 # Defaults to amd64
$ make build-cmd-cinder-csi-plugin
```
```

To build cinder-csi-plugin image

```
$ export ARCH=amd64 # Defaults to amd64
$ make build-local-image-cinder-csi-plugin
```
```

### Testing

Expand All @@ -284,7 +285,7 @@ To run all unit tests:
$ make test
```
#### Sanity Tests
Sanity tests ensures the CSI spec conformance of the driver. For more info, refer [Sanity check](https://github.com/kubernetes-csi/csi-test/tree/master/pkg/sanity)
Sanity tests ensures the CSI spec conformance of the driver. For more info, refer [Sanity check](https://github.com/kubernetes-csi/csi-test/tree/master/pkg/sanity)

Run sanity tests for cinder CSI driver using:

Expand All @@ -298,5 +299,5 @@ Optionally, to test the driver csc tool could be used. please refer, [usage guid

Starting from Kubernetes 1.21, OpenStack Cinder CSI migration is supported as beta feature and is `ON` by default. Cinder CSI driver must be installed on clusters on OpenStack for Cinder volumes to work. If you have persistence volumes that are created with in-tree `kubernetes.io/cinder` plugin, you could migrate to use `cinder.csi.openstack.org` Container Storage Interface (CSI) Driver.

* The CSI Migration feature for Cinder, when enabled, shims all plugin operations from the existing in-tree plugin to the `cinder.csi.openstack.org` CSI Driver.
* The CSI Migration feature for Cinder, when enabled, shims all plugin operations from the existing in-tree plugin to the `cinder.csi.openstack.org` CSI Driver.
* For more info, please refer [Migrate to CCM with CSI Migration](../openstack-cloud-controller-manager/migrate-to-ccm-with-csimigration.md#migrate-from-in-tree-cloud-provider-to-openstack-cloud-controller-manager-and-enable-csimigration) guide
6 changes: 4 additions & 2 deletions pkg/csi/cinder/controllerserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,12 +134,14 @@ func (cs *controllerServer) CreateVolume(ctx context.Context, req *csi.CreateVol
}
}

vol, err := cloud.CreateVolume(volName, volSizeGB, volType, volAvailability, snapshotID, sourcevolID, &properties)
// Volume Encryption
encrypted := (req.GetParameters()["encrypted"] == "true")

vol, err := cloud.CreateVolume(volName, volSizeGB, volType, encrypted, volAvailability, snapshotID, sourcevolID, &properties)

if err != nil {
klog.Errorf("Failed to CreateVolume: %v", err)
return nil, status.Errorf(codes.Internal, "CreateVolume failed with error %v", err)

}

klog.V(4).Infof("CreateVolume: Successfully created volume %s in Availability Zone: %s of size %d GiB", vol.ID, vol.AvailabilityZone, vol.Size)
Expand Down
2 changes: 1 addition & 1 deletion pkg/csi/cinder/nodeserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ func nodePublishEphemeral(req *csi.NodePublishVolumeRequest, ns *nodeServer) (*c
volumeType = ""
}

evol, err := ns.Cloud.CreateVolume(volName, size, volumeType, volAvailability, "", "", &properties)
evol, err := ns.Cloud.CreateVolume(volName, size, volumeType, false, volAvailability, "", "", &properties)

if err != nil {
klog.V(3).Infof("Failed to Create Ephemeral Volume: %v", err)
Expand Down
2 changes: 1 addition & 1 deletion pkg/csi/cinder/openstack/openstack.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func AddExtraFlags(fs *pflag.FlagSet) {
}

type IOpenStack interface {
CreateVolume(name string, size int, vtype, availability string, snapshotID string, sourcevolID string, tags *map[string]string) (*volumes.Volume, error)
CreateVolume(name string, size int, vtype string, encrypted bool, availability string, snapshotID string, sourcevolID string, tags *map[string]string) (*volumes.Volume, error)
DeleteVolume(volumeID string) error
AttachVolume(instanceID, volumeID string) (string, error)
ListVolumes(limit int, startingToken string) ([]volumes.Volume, string, error)
Expand Down
12 changes: 6 additions & 6 deletions pkg/csi/cinder/openstack/openstack_mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,20 +71,20 @@ func (_m *OpenStackMock) AttachVolume(instanceID string, volumeID string) (strin
return r0, r1
}

// CreateVolume provides a mock function with given fields: name, size, vtype, availability, tags
func (_m *OpenStackMock) CreateVolume(name string, size int, vtype string, availability string, snapshotID string, sourceVolID string, tags *map[string]string) (*volumes.Volume, error) {
// CreateVolume provides a mock function with given fields: name, size, vtype, encrypted, availability, tags
func (_m *OpenStackMock) CreateVolume(name string, size int, vtype string, encrypted bool, availability string, snapshotID string, sourceVolID string, tags *map[string]string) (*volumes.Volume, error) {
ret := _m.Called(name, size, vtype, availability, snapshotID, sourceVolID, tags)

var r0 *volumes.Volume
if rf, ok := ret.Get(0).(func(string, int, string, string, string, string, *map[string]string) *volumes.Volume); ok {
r0 = rf(name, size, vtype, availability, snapshotID, sourceVolID, tags)
if rf, ok := ret.Get(0).(func(string, int, string, bool, string, string, string, *map[string]string) *volumes.Volume); ok {
r0 = rf(name, size, vtype, encrypted, availability, snapshotID, sourceVolID, tags)
} else {
r0 = ret.Get(0).(*volumes.Volume)
}

var r1 error
if rf, ok := ret.Get(1).(func(string, int, string, string, string, string, *map[string]string) error); ok {
r1 = rf(name, size, vtype, availability, snapshotID, sourceVolID, tags)
if rf, ok := ret.Get(1).(func(string, int, string, bool, string, string, string, *map[string]string) error); ok {
r1 = rf(name, size, vtype, encrypted, availability, snapshotID, sourceVolID, tags)
} else {
r1 = ret.Error(1)
}
Expand Down
43 changes: 42 additions & 1 deletion pkg/csi/cinder/openstack/openstack_volumes.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"github.com/gophercloud/gophercloud/openstack"
volumeexpand "github.com/gophercloud/gophercloud/openstack/blockstorage/extensions/volumeactions"
"github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumes"
"github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumetypes"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/volumeattach"
"github.com/gophercloud/gophercloud/pagination"
"k8s.io/apimachinery/pkg/util/wait"
Expand Down Expand Up @@ -51,7 +52,20 @@ const (
var volumeErrorStates = [...]string{"error", "error_extending", "error_deleting"}

// CreateVolume creates a volume of given size
func (os *OpenStack) CreateVolume(name string, size int, vtype, availability string, snapshotID string, sourcevolID string, tags *map[string]string) (*volumes.Volume, error) {
func (os *OpenStack) CreateVolume(name string, size int, vtype string, encrypted bool, availability string, snapshotID string, sourcevolID string, tags *map[string]string) (*volumes.Volume, error) {
if encrypted {
volType, err := os.getVolumeTypeByName(vtype)
if err != nil {
return nil, err
} else if nil == volType {
return nil, fmt.Errorf("Failed to find the VolumeType %q given", vtype)
}

_, err = volumetypes.GetEncryption(os.blockstorage, volType.ID).Extract()
if err != nil {
return nil, err
}
}

opts := &volumes.CreateOpts{
Name: name,
Expand Down Expand Up @@ -412,6 +426,33 @@ func (os *OpenStack) diskIsUsed(volumeID string) (bool, error) {
return false, nil
}

// getVolumeTypeByName is a wrapper around ListVolumeTypes that creates a Name filter to act as a GetByUniqueName
// Returns the Volume Type referenced with the specified name
func (os *OpenStack) getVolumeTypeByName(n string) (*volumetypes.VolumeType, error) {
var matchingVolType *volumetypes.VolumeType

opts := volumetypes.ListOpts{}
volumetypes.List(os.blockstorage, opts).EachPage(func(page pagination.Page) (bool, error) {
var err error

volTypes, err := volumetypes.ExtractVolumeTypes(page)
if err != nil {
return false, err
}

for _, volType := range volTypes {
if n == volType.Name {
matchingVolType = &volType
return false, nil
}
}

return true, nil
})

return matchingVolType, nil
}

// GetBlockStorageOpts returns OpenStack block storage options
func (os *OpenStack) GetBlockStorageOpts() BlockStorageOpts {
return os.bsOpts
Expand Down
3 changes: 2 additions & 1 deletion tests/sanity/cinder/fakecloud.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func getfakecloud() *cloud {
var _ openstack.IOpenStack = &cloud{}

// Fake Cloud
func (cloud *cloud) CreateVolume(name string, size int, vtype, availability string, snapshotID string, sourceVolID string, tags *map[string]string) (*volumes.Volume, error) {
func (cloud *cloud) CreateVolume(name string, size int, vtype string, encrypted bool, availability string, snapshotID string, sourceVolID string, tags *map[string]string) (*volumes.Volume, error) {

vol := &volumes.Volume{
ID: randString(10),
Expand All @@ -43,6 +43,7 @@ func (cloud *cloud) CreateVolume(name string, size int, vtype, availability stri
AvailabilityZone: availability,
SnapshotID: snapshotID,
SourceVolID: sourceVolID,
Encrypted: encrypted,
}

cloud.volumes[vol.ID] = vol
Expand Down

0 comments on commit 86b647f

Please sign in to comment.