mirror of
https://github.com/TECHNOFAB11/zfs-localpv.git
synced 2025-12-12 06:20:11 +01:00
adding topology support for zfspv (#7)
This PR adds support to allow the CSI driver to pick up a node matching the topology specified in the storage class. Admin can specify allowedTopologies in the StorageClass to specify the nodes where the zfs pools are setup
```yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: openebs-zfspv
allowVolumeExpansion: true
parameters:
blocksize: "4k"
compression: "on"
dedup: "on"
thinprovision: "yes"
poolname: "zfspv-pool"
provisioner: zfs-localpv
volumeBindingMode: WaitForFirstConsumer
allowedTopologies:
- matchLabelExpressions:
- key: kubernetes.io/hostname
values:
- gke-zfspv-pawan-default-pool-c8929518-cgd4
- gke-zfspv-pawan-default-pool-c8929518-dxzc
```
Note: This PR picks up the first node from the list of nodes available.
Signed-off-by: Pawan <pawan@mayadata.io>
This commit is contained in:
parent
0218dacea0
commit
d0e97cddb2
11 changed files with 88 additions and 48 deletions
|
|
@ -136,6 +136,12 @@ func (b *Builder) WithThinProv(thinprov string) *Builder {
|
|||
return b
|
||||
}
|
||||
|
||||
// WithOwnerNode sets owner node for the ZFSVolume where the volume should be provisioned
|
||||
func (b *Builder) WithOwnerNode(host string) *Builder {
|
||||
b.volume.Object.Spec.OwnerNodeID = host
|
||||
return b
|
||||
}
|
||||
|
||||
// WithBlockSize sets blocksize of ZFSVolume
|
||||
func (b *Builder) WithBlockSize(blockSize string) *Builder {
|
||||
bs := "4k"
|
||||
|
|
|
|||
|
|
@ -181,8 +181,12 @@ func (ns *node) NodeGetInfo(
|
|||
req *csi.NodeGetInfoRequest,
|
||||
) (*csi.NodeGetInfoResponse, error) {
|
||||
|
||||
topology := map[string]string{zvol.ZFSTopologyKey: ns.driver.config.NodeID}
|
||||
return &csi.NodeGetInfoResponse{
|
||||
NodeId: ns.driver.config.NodeID,
|
||||
AccessibleTopology: &csi.Topology{
|
||||
Segments: topology,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -79,6 +79,9 @@ func (cs *controller) CreateVolume(
|
|||
pool := req.GetParameters()["poolname"]
|
||||
tp := req.GetParameters()["thinprovision"]
|
||||
|
||||
// setting first in preferred list as the ownernode of this volume
|
||||
OwnerNode := req.AccessibilityRequirements.Preferred[0].Segments[zvol.ZFSTopologyKey]
|
||||
|
||||
volObj, err := builder.NewBuilder().
|
||||
WithName(volName).
|
||||
WithCapacity(strconv.FormatInt(int64(size), 10)).
|
||||
|
|
@ -89,6 +92,7 @@ func (cs *controller) CreateVolume(
|
|||
WithKeyFormat(kf).
|
||||
WithKeyLocation(kl).
|
||||
WithThinProv(tp).
|
||||
WithOwnerNode(OwnerNode).
|
||||
WithCompression(compression).Build()
|
||||
|
||||
if err != nil {
|
||||
|
|
@ -100,9 +104,12 @@ func (cs *controller) CreateVolume(
|
|||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
|
||||
topology := map[string]string{zvol.ZFSTopologyKey: OwnerNode}
|
||||
|
||||
return csipayload.NewCreateVolumeResponseBuilder().
|
||||
WithName(volName).
|
||||
WithCapacity(size).
|
||||
WithTopology(topology).
|
||||
Build(), nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -57,6 +57,14 @@ func (b *CreateVolumeResponseBuilder) WithContext(ctx map[string]string) *Create
|
|||
return b
|
||||
}
|
||||
|
||||
// WithTopology sets the topology for the
|
||||
// CreateVolumeResponse instance
|
||||
func (b *CreateVolumeResponseBuilder) WithTopology(topology map[string]string) *CreateVolumeResponseBuilder {
|
||||
b.response.Volume.AccessibleTopology = make([]*csi.Topology, 1)
|
||||
b.response.Volume.AccessibleTopology[0] = &csi.Topology{Segments: topology}
|
||||
return b
|
||||
}
|
||||
|
||||
// Build returns the constructed instance
|
||||
// of csi CreateVolumeResponse
|
||||
func (b *CreateVolumeResponseBuilder) Build() *csi.CreateVolumeResponse {
|
||||
|
|
|
|||
|
|
@ -109,14 +109,9 @@ func CreateAndMountZvol(vol *apis.ZFSVolume, mount *apis.MountInfo) error {
|
|||
return status.Error(codes.Internal, "volume is owned by different node")
|
||||
}
|
||||
|
||||
devicePath, err := createZvol(vol)
|
||||
devicePath, err := GetDevicePath(vol)
|
||||
if err != nil {
|
||||
return status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
|
||||
err = UpdateZvolInfo(vol)
|
||||
if err != nil {
|
||||
return status.Error(codes.Internal, err.Error())
|
||||
return status.Error(codes.Internal, "not able to get the device path")
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -138,7 +133,7 @@ func CreateAndMountZvol(vol *apis.ZFSVolume, mount *apis.MountInfo) error {
|
|||
}
|
||||
err = FormatAndMountZvol(devicePath, mount)
|
||||
if err != nil {
|
||||
return status.Error(codes.Internal, err.Error())
|
||||
return status.Error(codes.Internal, "not able to mount the volume")
|
||||
}
|
||||
|
||||
return err
|
||||
|
|
|
|||
|
|
@ -31,9 +31,10 @@ const (
|
|||
OpenEBSNamespaceKey string = "OPENEBS_NAMESPACE"
|
||||
// ZFSFinalizer for the ZfsVolume CR
|
||||
ZFSFinalizer string = "zfs.openebs.io/finalizer"
|
||||
// ZFSNodeKey will be used to insert Label
|
||||
// in ZfsVolume CR
|
||||
// ZFSNodeKey will be used to insert Label in ZfsVolume CR
|
||||
ZFSNodeKey string = "kubernetes.io/nodename"
|
||||
// ZFSTopologyKey is supported topology key for the zfs driver
|
||||
ZFSTopologyKey string = "kubernetes.io/hostname"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
|
|||
|
|
@ -119,9 +119,9 @@ func buildVolumeDestroyArgs(vol *apis.ZFSVolume) []string {
|
|||
return ZFSVolCmd
|
||||
}
|
||||
|
||||
// createZvol creates the zvol and returns the corresponding diskPath
|
||||
// CreateZvol creates the zvol and returns the corresponding diskPath
|
||||
// of the volume which gets created on the node
|
||||
func createZvol(vol *apis.ZFSVolume) (string, error) {
|
||||
func CreateZvol(vol *apis.ZFSVolume) error {
|
||||
zvol := vol.Spec.PoolName + "/" + vol.Name
|
||||
devicePath := ZFS_DEVPATH + zvol
|
||||
|
||||
|
|
@ -135,16 +135,16 @@ func createZvol(vol *apis.ZFSVolume) (string, error) {
|
|||
logrus.Errorf(
|
||||
"zfs: could not create zvol %v cmd %v error: %s", zvol, args, string(out),
|
||||
)
|
||||
return "", err
|
||||
return err
|
||||
}
|
||||
logrus.Infof("created zvol %s", zvol)
|
||||
} else if err == nil {
|
||||
logrus.Infof("using existing zvol %v", zvol)
|
||||
} else {
|
||||
return "", err
|
||||
return err
|
||||
}
|
||||
|
||||
return devicePath, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetZvolProp sets the zvol property
|
||||
|
|
@ -191,3 +191,14 @@ func DestroyZvol(vol *apis.ZFSVolume) error {
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetDevicePath returns device path for zvol if it exists
|
||||
func GetDevicePath(vol *apis.ZFSVolume) (string, error) {
|
||||
zvol := vol.Spec.PoolName + "/" + vol.Name
|
||||
devicePath := ZFS_DEVPATH + zvol
|
||||
|
||||
if _, err := os.Stat(devicePath); os.IsNotExist(err) {
|
||||
return "", err
|
||||
}
|
||||
return devicePath, nil
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue