mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-13 02:33:34 +00:00
cleanup: Remove support for Delete and Unmounting v1.1.0 PVC
as v1.0.0 is deprecated we need to remove the support for it in the Next coming (v3.0.0) release. This PR removes the support for the same. closes #882 Signed-off-by: Madhu Rajanna <madhupr007@gmail.com>
This commit is contained in:
committed by
mergify[bot]
parent
a0fd805a8b
commit
d15ded88f5
@ -1,56 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The Ceph-CSI 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 util
|
||||
|
||||
import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
// ForAllFunc is a unary predicate for visiting all cache entries
|
||||
// matching the `pattern' in CachePersister's ForAll function.
|
||||
type ForAllFunc func(identifier string) error
|
||||
|
||||
// CacheEntryNotFound is an error type for "Not Found" cache errors
|
||||
type CacheEntryNotFound struct {
|
||||
error
|
||||
}
|
||||
|
||||
// CachePersister interface implemented for store
|
||||
type CachePersister interface {
|
||||
Create(identifier string, data interface{}) error
|
||||
Get(identifier string, data interface{}) error
|
||||
ForAll(pattern string, destObj interface{}, f ForAllFunc) error
|
||||
Delete(identifier string) error
|
||||
}
|
||||
|
||||
// NewCachePersister returns CachePersister based on store
|
||||
func NewCachePersister(metadataStore, pluginPath string) (CachePersister, error) {
|
||||
if metadataStore == "k8s_configmap" {
|
||||
DebugLogMsg("cache-perister: using kubernetes configmap as metadata cache persister")
|
||||
k8scm := &K8sCMCache{}
|
||||
k8scm.Client = NewK8sClient()
|
||||
k8scm.Namespace = GetK8sNamespace()
|
||||
return k8scm, nil
|
||||
} else if metadataStore == "node" {
|
||||
DebugLogMsg("cache-persister: using node as metadata cache persister")
|
||||
nc := &NodeCache{}
|
||||
nc.BasePath = pluginPath
|
||||
nc.CacheDir = "controller"
|
||||
return nc, nil
|
||||
}
|
||||
return nil, errors.New("cache-persister: couldn't parse metadatastorage flag")
|
||||
}
|
52
internal/util/k8s.go
Normal file
52
internal/util/k8s.go
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
Copyright 2020 The CephCSI 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/LICENSE2.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 util
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
k8s "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
klog "k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
// NewK8sClient create kubernetes client
|
||||
func NewK8sClient() *k8s.Clientset {
|
||||
var cfg *rest.Config
|
||||
var err error
|
||||
cPath := os.Getenv("KUBERNETES_CONFIG_PATH")
|
||||
if cPath != "" {
|
||||
cfg, err = clientcmd.BuildConfigFromFlags("", cPath)
|
||||
if err != nil {
|
||||
klog.Errorf("Failed to get cluster config with error: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
} else {
|
||||
cfg, err = rest.InClusterConfig()
|
||||
if err != nil {
|
||||
klog.Errorf("Failed to get cluster config with error: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
client, err := k8s.NewForConfig(cfg)
|
||||
if err != nil {
|
||||
klog.Errorf("Failed to create client with error: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
return client
|
||||
}
|
@ -1,187 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The Ceph-CSI 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 util
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
|
||||
v1 "k8s.io/api/core/v1"
|
||||
apierrs "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
k8s "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
klog "k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
// K8sCMCache to store metadata
|
||||
type K8sCMCache struct {
|
||||
Client *k8s.Clientset
|
||||
Namespace string
|
||||
}
|
||||
|
||||
const (
|
||||
defaultNamespace = "default"
|
||||
|
||||
cmLabel = "csi-metadata"
|
||||
cmDataKey = "content"
|
||||
|
||||
csiMetadataLabelAttr = "com.ceph.ceph-csi/metadata"
|
||||
)
|
||||
|
||||
// GetK8sNamespace returns pod namespace. if pod namespace is empty
|
||||
// it returns default namespace
|
||||
func GetK8sNamespace() string {
|
||||
namespace := os.Getenv("POD_NAMESPACE")
|
||||
if namespace == "" {
|
||||
return defaultNamespace
|
||||
}
|
||||
return namespace
|
||||
}
|
||||
|
||||
// NewK8sClient create kubernetes client
|
||||
func NewK8sClient() *k8s.Clientset {
|
||||
var cfg *rest.Config
|
||||
var err error
|
||||
cPath := os.Getenv("KUBERNETES_CONFIG_PATH")
|
||||
if cPath != "" {
|
||||
cfg, err = clientcmd.BuildConfigFromFlags("", cPath)
|
||||
if err != nil {
|
||||
klog.Errorf("Failed to get cluster config with error: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
} else {
|
||||
cfg, err = rest.InClusterConfig()
|
||||
if err != nil {
|
||||
klog.Errorf("Failed to get cluster config with error: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
client, err := k8s.NewForConfig(cfg)
|
||||
if err != nil {
|
||||
klog.Errorf("Failed to create client with error: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
return client
|
||||
}
|
||||
|
||||
func (k8scm *K8sCMCache) getMetadataCM(resourceID string) (*v1.ConfigMap, error) {
|
||||
cm, err := k8scm.Client.CoreV1().ConfigMaps(k8scm.Namespace).Get(context.TODO(), resourceID, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return cm, nil
|
||||
}
|
||||
|
||||
// ForAll list the metadata in configmaps and filters outs based on the pattern
|
||||
func (k8scm *K8sCMCache) ForAll(pattern string, destObj interface{}, f ForAllFunc) error {
|
||||
listOpts := metav1.ListOptions{LabelSelector: fmt.Sprintf("%s=%s", csiMetadataLabelAttr, cmLabel)}
|
||||
cms, err := k8scm.Client.CoreV1().ConfigMaps(k8scm.Namespace).List(context.TODO(), listOpts)
|
||||
if err != nil {
|
||||
return fmt.Errorf("k8s-cm-cache: failed to list metadata configmaps: %w", err)
|
||||
}
|
||||
|
||||
for i := range cms.Items {
|
||||
data := cms.Items[i].Data[cmDataKey]
|
||||
match, err := regexp.MatchString(pattern, cms.Items[i].ObjectMeta.Name)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if !match {
|
||||
continue
|
||||
}
|
||||
if err = json.Unmarshal([]byte(data), destObj); err != nil {
|
||||
return fmt.Errorf("k8s-cm-cache: JSON unmarshaling failed for configmap %s: %w", cms.Items[i].ObjectMeta.Name, err)
|
||||
}
|
||||
if err = f(cms.Items[i].ObjectMeta.Name); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Create stores the metadata in configmaps with identifier name
|
||||
func (k8scm *K8sCMCache) Create(identifier string, data interface{}) error {
|
||||
cm, err := k8scm.getMetadataCM(identifier)
|
||||
if cm != nil && err == nil {
|
||||
DebugLogMsg("k8s-cm-cache: configmap %s already exists, skipping configmap creation", identifier)
|
||||
return nil
|
||||
}
|
||||
dataJSON, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
return fmt.Errorf("k8s-cm-cache: JSON marshaling failed for configmap %s: %w", identifier, err)
|
||||
}
|
||||
cm = &v1.ConfigMap{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: identifier,
|
||||
Namespace: k8scm.Namespace,
|
||||
Labels: map[string]string{
|
||||
csiMetadataLabelAttr: cmLabel,
|
||||
},
|
||||
},
|
||||
Data: map[string]string{},
|
||||
}
|
||||
cm.Data[cmDataKey] = string(dataJSON)
|
||||
|
||||
_, err = k8scm.Client.CoreV1().ConfigMaps(k8scm.Namespace).Create(context.TODO(), cm, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
if apierrs.IsAlreadyExists(err) {
|
||||
DebugLogMsg("k8s-cm-cache: configmap %s already exists", identifier)
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("k8s-cm-cache: couldn't persist %s metadata as configmap: %w", identifier, err)
|
||||
}
|
||||
|
||||
DebugLogMsg("k8s-cm-cache: configmap %s successfully created", identifier)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get retrieves the metadata in configmaps with identifier name
|
||||
func (k8scm *K8sCMCache) Get(identifier string, data interface{}) error {
|
||||
cm, err := k8scm.getMetadataCM(identifier)
|
||||
if err != nil {
|
||||
if apierrs.IsNotFound(err) {
|
||||
return &CacheEntryNotFound{err}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
err = json.Unmarshal([]byte(cm.Data[cmDataKey]), data)
|
||||
if err != nil {
|
||||
return fmt.Errorf("k8s-cm-cache: JSON unmarshaling failed for configmap %s: %w", identifier, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Delete deletes the metadata in configmaps with identifier name
|
||||
func (k8scm *K8sCMCache) Delete(identifier string) error {
|
||||
err := k8scm.Client.CoreV1().ConfigMaps(k8scm.Namespace).Delete(context.TODO(), identifier, metav1.DeleteOptions{})
|
||||
if err != nil {
|
||||
if apierrs.IsNotFound(err) {
|
||||
DebugLogMsg("k8s-cm-cache: cannot delete missing metadata configmap %s, assuming it's already deleted", identifier)
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("k8s-cm-cache: couldn't delete metadata configmap %s: %w", identifier, err)
|
||||
}
|
||||
DebugLogMsg("k8s-cm-cache: successfully deleted metadata configmap %s", identifier)
|
||||
return nil
|
||||
}
|
@ -1,165 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The Ceph-CSI 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 util
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
klog "k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
// NodeCache to store metadata
|
||||
type NodeCache struct {
|
||||
BasePath string
|
||||
CacheDir string
|
||||
}
|
||||
|
||||
var errDec = errors.New("file not found")
|
||||
|
||||
// EnsureCacheDirectory creates cache directory if not present
|
||||
func (nc *NodeCache) EnsureCacheDirectory(cacheDir string) error {
|
||||
fullPath := path.Join(nc.BasePath, cacheDir)
|
||||
if _, err := os.Stat(fullPath); os.IsNotExist(err) {
|
||||
// #nosec
|
||||
if err := os.Mkdir(fullPath, 0755); err != nil {
|
||||
return fmt.Errorf("node-cache: failed to create %s folder: %w", fullPath, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ForAll list the metadata in Nodecache and filters outs based on the pattern
|
||||
func (nc *NodeCache) ForAll(pattern string, destObj interface{}, f ForAllFunc) error {
|
||||
err := nc.EnsureCacheDirectory(nc.CacheDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("node-cache: couldn't ensure cache directory exists: %w", err)
|
||||
}
|
||||
files, err := ioutil.ReadDir(path.Join(nc.BasePath, nc.CacheDir))
|
||||
if err != nil {
|
||||
return fmt.Errorf("node-cache: failed to read %s folder: %w", nc.BasePath, err)
|
||||
}
|
||||
cachePath := path.Join(nc.BasePath, nc.CacheDir)
|
||||
for _, file := range files {
|
||||
err = decodeObj(cachePath, pattern, file, destObj)
|
||||
if errors.Is(err, errDec) {
|
||||
continue
|
||||
} else if err == nil {
|
||||
if err = f(strings.TrimSuffix(file.Name(), filepath.Ext(file.Name()))); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func decodeObj(fpath, pattern string, file os.FileInfo, destObj interface{}) error {
|
||||
match, err := regexp.MatchString(pattern, file.Name())
|
||||
if err != nil || !match {
|
||||
return errDec
|
||||
}
|
||||
if !strings.HasSuffix(file.Name(), ".json") {
|
||||
return errDec
|
||||
}
|
||||
// #nosec
|
||||
fp, err := os.Open(path.Join(fpath, file.Name()))
|
||||
if err != nil {
|
||||
DebugLogMsg("node-cache: open file: %s err %v", file.Name(), err)
|
||||
return errDec
|
||||
}
|
||||
decoder := json.NewDecoder(fp)
|
||||
if err = decoder.Decode(destObj); err != nil {
|
||||
if err = fp.Close(); err != nil {
|
||||
return fmt.Errorf("failed to close file %s: %w", file.Name(), err)
|
||||
}
|
||||
return fmt.Errorf("node-cache: couldn't decode file %s: %w", file.Name(), err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Create creates the metadata file in cache directory with identifier name
|
||||
func (nc *NodeCache) Create(identifier string, data interface{}) error {
|
||||
file := path.Join(nc.BasePath, nc.CacheDir, identifier+".json")
|
||||
fp, err := os.Create(file)
|
||||
if err != nil {
|
||||
return fmt.Errorf("node-cache: failed to create metadata storage file %s: %w", file, err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err = fp.Close(); err != nil {
|
||||
klog.Warningf("failed to close file:%s %v", fp.Name(), err)
|
||||
}
|
||||
}()
|
||||
|
||||
encoder := json.NewEncoder(fp)
|
||||
if err = encoder.Encode(data); err != nil {
|
||||
return fmt.Errorf("node-cache: failed to encode metadata for file: %s: %w", file, err)
|
||||
}
|
||||
DebugLogMsg("node-cache: successfully saved metadata into file: %s\n", file)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get retrieves the metadata from cache directory with identifier name
|
||||
func (nc *NodeCache) Get(identifier string, data interface{}) error {
|
||||
file := path.Join(nc.BasePath, nc.CacheDir, identifier+".json")
|
||||
// #nosec
|
||||
fp, err := os.Open(file)
|
||||
if err != nil {
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
return &CacheEntryNotFound{err}
|
||||
}
|
||||
|
||||
return fmt.Errorf("node-cache: open error for %s: %w", file, err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err = fp.Close(); err != nil {
|
||||
klog.Warningf("failed to close file:%s %v", fp.Name(), err)
|
||||
}
|
||||
}()
|
||||
|
||||
decoder := json.NewDecoder(fp)
|
||||
if err = decoder.Decode(data); err != nil {
|
||||
return fmt.Errorf("rbd: decode error: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Delete deletes the metadata file from cache directory with identifier name
|
||||
func (nc *NodeCache) Delete(identifier string) error {
|
||||
file := path.Join(nc.BasePath, nc.CacheDir, identifier+".json")
|
||||
err := os.Remove(file)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
DebugLogMsg("node-cache: cannot delete missing metadata storage file %s, assuming it's already deleted", file)
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("node-cache: error removing file %s: %w", file, err)
|
||||
}
|
||||
DebugLogMsg("node-cache: successfully deleted metadata storage file at: %+v\n", file)
|
||||
return nil
|
||||
}
|
@ -22,7 +22,6 @@ import (
|
||||
"fmt"
|
||||
"math"
|
||||
"os"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@ -79,17 +78,13 @@ var (
|
||||
|
||||
// Config holds the parameters list which can be configured
|
||||
type Config struct {
|
||||
Vtype string // driver type [rbd|cephfs|liveness]
|
||||
Endpoint string // CSI endpoint
|
||||
DriverName string // name of the driver
|
||||
NodeID string // node id
|
||||
InstanceID string // unique ID distinguishing this instance of Ceph CSI
|
||||
MetadataStorage string // metadata persistence method [node|k8s_configmap]
|
||||
PluginPath string // location of cephcsi plugin
|
||||
DomainLabels string // list of domain labels to read from the node
|
||||
|
||||
// cephfs related flags
|
||||
MountCacheDir string // mount info cache save dir
|
||||
Vtype string // driver type [rbd|cephfs|liveness]
|
||||
Endpoint string // CSI endpoint
|
||||
DriverName string // name of the driver
|
||||
NodeID string // node id
|
||||
InstanceID string // unique ID distinguishing this instance of Ceph CSI
|
||||
PluginPath string // location of cephcsi plugin
|
||||
DomainLabels string // list of domain labels to read from the node
|
||||
|
||||
// metrics related flags
|
||||
MetricsPath string // path of prometheus endpoint where metrics will be available
|
||||
@ -124,27 +119,6 @@ type Config struct {
|
||||
MaxSnapshotsOnImage uint
|
||||
}
|
||||
|
||||
// CreatePersistanceStorage creates storage path and initializes new cache
|
||||
func CreatePersistanceStorage(sPath, metaDataStore, pluginPath string) (CachePersister, error) {
|
||||
var err error
|
||||
if err = CreateMountPoint(path.Join(sPath, "controller")); err != nil {
|
||||
klog.Errorf("failed to create persistent storage for controller: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = CreateMountPoint(path.Join(sPath, "node")); err != nil {
|
||||
klog.Errorf("failed to create persistent storage for node: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cp, err := NewCachePersister(metaDataStore, pluginPath)
|
||||
if err != nil {
|
||||
klog.Errorf("failed to define cache persistence method: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
return cp, err
|
||||
}
|
||||
|
||||
// ValidateDriverName validates the driver name
|
||||
func ValidateDriverName(driverName string) error {
|
||||
if driverName == "" {
|
||||
|
Reference in New Issue
Block a user