mirror of
https://github.com/TECHNOFAB11/zfs-localpv.git
synced 2025-12-12 06:20:11 +01:00
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>
204 lines
5.5 KiB
Go
204 lines
5.5 KiB
Go
/*
|
|
Copyright 2017 The Kubernetes Authors.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License 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 zfs
|
|
|
|
import (
|
|
"os"
|
|
"os/exec"
|
|
|
|
"github.com/Sirupsen/logrus"
|
|
apis "github.com/openebs/zfs-localpv/pkg/apis/openebs.io/core/v1alpha1"
|
|
)
|
|
|
|
const (
|
|
ZFS_DEVPATH = "/dev/zvol/"
|
|
ZFSVolCmd = "zfs"
|
|
ZFSCreateArg = "create"
|
|
ZFSDestroyArg = "destroy"
|
|
ZFSSetArg = "set"
|
|
)
|
|
|
|
func PropertyChanged(oldVol *apis.ZFSVolume, newVol *apis.ZFSVolume) bool {
|
|
return oldVol.Spec.Compression != newVol.Spec.Compression ||
|
|
oldVol.Spec.Dedup != newVol.Spec.Dedup ||
|
|
oldVol.Spec.Capacity != newVol.Spec.Capacity
|
|
}
|
|
|
|
// builldVolumeCreateArgs returns zvol create command along with attributes as a string array
|
|
func buildVolumeCreateArgs(vol *apis.ZFSVolume) []string {
|
|
var ZFSVolCmd []string
|
|
|
|
zvol := vol.Spec.PoolName + "/" + vol.Name
|
|
|
|
ZFSVolCmd = append(ZFSVolCmd, ZFSCreateArg)
|
|
|
|
if vol.Spec.ThinProvision == "yes" {
|
|
ZFSVolCmd = append(ZFSVolCmd, "-s")
|
|
}
|
|
if len(vol.Spec.Capacity) != 0 {
|
|
ZFSVolCmd = append(ZFSVolCmd, "-V", vol.Spec.Capacity)
|
|
}
|
|
if len(vol.Spec.BlockSize) != 0 {
|
|
ZFSVolCmd = append(ZFSVolCmd, "-b", vol.Spec.BlockSize)
|
|
}
|
|
if len(vol.Spec.Dedup) != 0 {
|
|
dedupProperty := "dedup=" + vol.Spec.Dedup
|
|
ZFSVolCmd = append(ZFSVolCmd, "-o", dedupProperty)
|
|
}
|
|
if len(vol.Spec.Compression) != 0 {
|
|
compressionProperty := "compression=" + vol.Spec.Compression
|
|
ZFSVolCmd = append(ZFSVolCmd, "-o", compressionProperty)
|
|
}
|
|
if len(vol.Spec.Encryption) != 0 {
|
|
encryptionProperty := "encryption=" + vol.Spec.Encryption
|
|
ZFSVolCmd = append(ZFSVolCmd, "-o", encryptionProperty)
|
|
}
|
|
if len(vol.Spec.KeyLocation) != 0 {
|
|
keyLocation := "keylocation=" + vol.Spec.KeyLocation
|
|
ZFSVolCmd = append(ZFSVolCmd, "-o", keyLocation)
|
|
}
|
|
if len(vol.Spec.KeyFormat) != 0 {
|
|
keyFormat := "keyformat=" + vol.Spec.KeyFormat
|
|
ZFSVolCmd = append(ZFSVolCmd, "-o", keyFormat)
|
|
}
|
|
|
|
ZFSVolCmd = append(ZFSVolCmd, zvol)
|
|
|
|
return ZFSVolCmd
|
|
}
|
|
|
|
// builldVolumeSetArgs returns zvol set command along with attributes as a string array
|
|
// TODO(pawan) need to find a way to identify which property has changed
|
|
func buildVolumeSetArgs(vol *apis.ZFSVolume) []string {
|
|
var ZFSVolCmd []string
|
|
|
|
zvol := vol.Spec.PoolName + "/" + vol.Name
|
|
|
|
ZFSVolCmd = append(ZFSVolCmd, ZFSSetArg)
|
|
|
|
if len(vol.Spec.Capacity) != 0 {
|
|
volsize := "volsize=" + vol.Spec.Capacity
|
|
ZFSVolCmd = append(ZFSVolCmd, volsize)
|
|
}
|
|
if len(vol.Spec.Dedup) != 0 {
|
|
dedupProperty := "dedup=" + vol.Spec.Dedup
|
|
ZFSVolCmd = append(ZFSVolCmd, dedupProperty)
|
|
}
|
|
if len(vol.Spec.Compression) != 0 {
|
|
compressionProperty := "compression=" + vol.Spec.Compression
|
|
ZFSVolCmd = append(ZFSVolCmd, compressionProperty)
|
|
}
|
|
|
|
ZFSVolCmd = append(ZFSVolCmd, zvol)
|
|
|
|
return ZFSVolCmd
|
|
}
|
|
|
|
// builldVolumeDestroyArgs returns zvol destroy command along with attributes as a string array
|
|
func buildVolumeDestroyArgs(vol *apis.ZFSVolume) []string {
|
|
var ZFSVolCmd []string
|
|
|
|
zvol := vol.Spec.PoolName + "/" + vol.Name
|
|
|
|
ZFSVolCmd = append(ZFSVolCmd, ZFSDestroyArg, "-R", zvol)
|
|
|
|
return ZFSVolCmd
|
|
}
|
|
|
|
// CreateZvol creates the zvol and returns the corresponding diskPath
|
|
// of the volume which gets created on the node
|
|
func CreateZvol(vol *apis.ZFSVolume) error {
|
|
zvol := vol.Spec.PoolName + "/" + vol.Name
|
|
devicePath := ZFS_DEVPATH + zvol
|
|
|
|
if _, err := os.Stat(devicePath); os.IsNotExist(err) {
|
|
|
|
args := buildVolumeCreateArgs(vol)
|
|
cmd := exec.Command(ZFSVolCmd, args...)
|
|
out, err := cmd.CombinedOutput()
|
|
|
|
if err != nil {
|
|
logrus.Errorf(
|
|
"zfs: could not create zvol %v cmd %v error: %s", zvol, args, string(out),
|
|
)
|
|
return err
|
|
}
|
|
logrus.Infof("created zvol %s", zvol)
|
|
} else if err == nil {
|
|
logrus.Infof("using existing zvol %v", zvol)
|
|
} else {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// SetZvolProp sets the zvol property
|
|
func SetZvolProp(vol *apis.ZFSVolume) error {
|
|
var err error
|
|
zvol := vol.Spec.PoolName + "/" + vol.Name
|
|
devicePath := ZFS_DEVPATH + zvol
|
|
|
|
if _, err = os.Stat(devicePath); err == nil {
|
|
args := buildVolumeSetArgs(vol)
|
|
cmd := exec.Command(ZFSVolCmd, args...)
|
|
out, err := cmd.CombinedOutput()
|
|
|
|
if err != nil {
|
|
logrus.Errorf(
|
|
"zfs: could not set property on zvol %v cmd %v error: %s", zvol, args, string(out),
|
|
)
|
|
return err
|
|
}
|
|
logrus.Infof("property set on zvol %s", zvol)
|
|
}
|
|
|
|
return err
|
|
}
|
|
|
|
// DestroyZvol deletes the zvol
|
|
func DestroyZvol(vol *apis.ZFSVolume) error {
|
|
zvol := vol.Spec.PoolName + "/" + vol.Name
|
|
devicePath := ZFS_DEVPATH + zvol
|
|
|
|
if _, err := os.Stat(devicePath); err == nil {
|
|
args := buildVolumeDestroyArgs(vol)
|
|
cmd := exec.Command(ZFSVolCmd, args...)
|
|
out, err := cmd.CombinedOutput()
|
|
|
|
if err != nil {
|
|
logrus.Errorf(
|
|
"zfs: could not destroy zvol %v cmd %v error: %s", zvol, args, string(out),
|
|
)
|
|
return err
|
|
}
|
|
logrus.Infof("destroyed zvol %s", zvol)
|
|
}
|
|
|
|
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
|
|
}
|