Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(spc): add capability to specify allowed BD tags on SPC #1748

Merged
merged 3 commits into from
Sep 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion cmd/maya-apiserver/app/server/restore_endpoint_v1alpha1.go
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,6 @@ func updateRestoreStatus(clientset versioned.Interface, rst v1alpha1.CStorRestor

func createVolumeForRestore(r *v1alpha1.CStorRestore) (*v1alpha1.CASVolume, error) {
vol := &v1alpha1.CASVolume{}

vol.Name = r.Spec.VolumeName
vol.Labels = map[string]string{
string(v1alpha1.StorageClassKey): r.Spec.StorageClass,
Expand Down
57 changes: 53 additions & 4 deletions pkg/algorithm/nodeselect/v1alpha1/select_node.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,21 @@ import (
bdc "github.com/openebs/maya/pkg/blockdeviceclaim/v1alpha1"
env "github.com/openebs/maya/pkg/env/v1alpha1"
spcv1alpha1 "github.com/openebs/maya/pkg/storagepoolclaim/v1alpha1"
util "github.com/openebs/maya/pkg/util"
volume "github.com/openebs/maya/pkg/volume"
"github.com/openebs/maya/pkg/util"
"github.com/openebs/maya/pkg/volume"
"github.com/pkg/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/klog"
"strings"
)

const (
// CStorBDTagAnnotationKey is the annotation key for SPC allowed BD tags
CStorBDTagAnnotationKey = "openebs.io/allowed-bd-tags"
// BlockDeviceTagLabelKey is the key to fetch tag of a block
// device.
// For more info : https://github.com/openebs/node-disk-manager/pull/400
BlockDeviceTagLabelKey = "openebs.io/block-device-tag"
)

// BDDetails holds the claimed block device details
Expand Down Expand Up @@ -273,7 +283,7 @@ func (ac *Config) getBlockDevice() (*ndmapis.BlockDeviceList, error) {
if err != nil {
return nil, err
}
filterList := []string{blockdevice.FilterNonInactive}
filterList := []string{blockdevice.FilterNonInactive, blockdevice.FilterNotAllowedBDTag}

if diskType == string(apis.TypeSparseCPV) {
filterList = append(filterList, blockdevice.FilterSparseDevices)
Expand All @@ -285,7 +295,12 @@ func (ac *Config) getBlockDevice() (*ndmapis.BlockDeviceList, error) {
filterList = append(filterList, blockdevice.FilterNonFSType, blockdevice.FilterNonRelesedDevices)
}

bdl = bdList.Filter(filterList...)
allowedBDTags := getAllowedTagMap(ac.Spc.GetAnnotations())
filterOptions := &blockdevice.FilterOptions{
AllowedBDTags: allowedBDTags,
}

bdl = bdList.Filter(filterOptions, filterList...)
if len(bdl.Items) == 0 {
return nil, errors.Errorf("type {%s} devices are not available to provision pools in %s mode", diskType, ProvisioningType(ac.Spc))
}
Expand Down Expand Up @@ -355,6 +370,7 @@ func (ac *Config) ClaimBlockDevice(nodeBDs *nodeBlockDevice, spc *apis.StoragePo
continue
}
capacity := volume.ByteCount(bdObj.Spec.Capacity.Storage)

//TODO: Move below code to some function
newBDCObj, err := bdc.NewBuilder().
WithName(bdcName).
Expand All @@ -366,6 +382,16 @@ func (ac *Config) ClaimBlockDevice(nodeBDs *nodeBlockDevice, spc *apis.StoragePo
WithOwnerReference(spc).
WithFinalizer(spcv1alpha1.SPCFinalizer).
Build()

value, ok := bdObj.Labels[BlockDeviceTagLabelKey]

if ok {
ls := &metav1.LabelSelector{
MatchLabels: map[string]string{BlockDeviceTagLabelKey: value},
}
newBDCObj.Object.Spec.Selector = ls
}

if err != nil {
return nil, errors.Wrapf(err, "failed to build block device claim for bd {%s}", bdName)
}
Expand All @@ -388,3 +414,26 @@ func (ac *Config) ClaimBlockDevice(nodeBDs *nodeBlockDevice, spc *apis.StoragePo
}
return nodeClaimedBDs, nil
}

// getAllowedTagMap returns a map of the allowed BD tags
// Example :
// If the CSPC annotation is passed and following is the BD tag annotation
//
// cstor.openebs.io/allowed-bd-tags:fast,slow
//
// Then, a map {"fast":true,"slow":true} is returned.
func getAllowedTagMap(cspcAnnotation map[string]string) map[string]bool {
allowedTagsMap := make(map[string]bool)
allowedTags := cspcAnnotation[CStorBDTagAnnotationKey]
if strings.TrimSpace(allowedTags) == "" {
return allowedTagsMap
}
allowedTagsList := strings.Split(allowedTags, ",")
for _, v := range allowedTagsList {
if strings.TrimSpace(v) == "" {
continue
}
allowedTagsMap[v] = true
}
return allowedTagsMap
}
83 changes: 83 additions & 0 deletions pkg/algorithm/nodeselect/v1alpha1/select_node_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ limitations under the License.
package v1alpha1

import (
"reflect"
"strconv"
"testing"

Expand Down Expand Up @@ -547,3 +548,85 @@ func TestNodeBlockDeviceAlloter(t *testing.T) {
})
}
}

func Test_getAllowedTagMap(t *testing.T) {
type args struct {
cspcAnnotation map[string]string
}
tests := []struct {
name string
args args
want map[string]bool
}{
{
name: "Test case #1",
args: args{
cspcAnnotation: map[string]string{CStorBDTagAnnotationKey: "fast,slow"},
},
want: map[string]bool{"fast": true, "slow": true},
},

{
name: "Test case #2",
args: args{
cspcAnnotation: map[string]string{CStorBDTagAnnotationKey: "fast,slow"},
},
want: map[string]bool{"slow": true, "fast": true},
},

{
name: "Test case #3 -- Nil Annotations",
args: args{
cspcAnnotation: nil,
},
want: map[string]bool{},
},

{
name: "Test case #4 -- No BD tag Annotations",
args: args{
cspcAnnotation: map[string]string{"some-other-annotation-key": "awesome-openebs"},
},
want: map[string]bool{},
},

{
name: "Test case #5 -- Improper format 1",
args: args{
cspcAnnotation: map[string]string{CStorBDTagAnnotationKey: ",fast,slow,,"},
},
want: map[string]bool{"fast": true, "slow": true},
},

{
name: "Test case #6 -- Improper format 2",
args: args{
cspcAnnotation: map[string]string{CStorBDTagAnnotationKey: ",fast,slow"},
},
want: map[string]bool{"fast": true, "slow": true},
},

{
name: "Test case #7 -- Improper format 2",
args: args{
cspcAnnotation: map[string]string{CStorBDTagAnnotationKey: ",fast,,slow"},
},
want: map[string]bool{"fast": true, "slow": true},
},

{
name: "Test case #7 -- Improper format 2",
args: args{
cspcAnnotation: map[string]string{CStorBDTagAnnotationKey: "this is improper"},
},
want: map[string]bool{"this is improper": true},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := getAllowedTagMap(tt.args.cspcAnnotation); !reflect.DeepEqual(got, tt.want) {
t.Errorf("getAllowedTagMap() = %v, want %v", got, tt.want)
}
})
}
}
40 changes: 38 additions & 2 deletions pkg/blockdevice/v1alpha1/blockdevice.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import (
ndm "github.com/openebs/maya/pkg/apis/openebs.io/ndm/v1alpha1"
apis "github.com/openebs/maya/pkg/apis/openebs.io/v1alpha1"
bdc_v1alpha1 "github.com/openebs/maya/pkg/blockdeviceclaim/v1alpha1"
errors "github.com/pkg/errors"
"github.com/pkg/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"

Expand All @@ -40,8 +40,16 @@ const (
FilterNonSparseDevices = "filterNonSparseDevices"
InActiveStatus = "Inactive"
FilterNonRelesedDevices = "filterNonRelesedDevices"
FilterNotAllowedBDTag = "filterNotAllowedBDTag"

// BlockDeviceTagLabelKey is the key to fetch tag of a block
// device.
// For more info : https://github.com/openebs/node-disk-manager/pull/400
BlockDeviceTagLabelKey = "openebs.io/block-device-tag"
)

var bdFilterOptions FilterOptions

// KubernetesClient is the kubernetes client which will implement block device actions/behaviours
type KubernetesClient struct {
// Kubeclientset is a standard kubernetes clientset
Expand Down Expand Up @@ -111,6 +119,7 @@ var filterOptionFuncMap = map[string]filterOptionFunc{
FilterSparseDevices: filterSparseDevices,
FilterNonSparseDevices: filterNonSparseDevices,
FilterNonRelesedDevices: filterNonRelesedDevices,
FilterNotAllowedBDTag: filterNotAllowedBDTag,
}

// predicateFailedError returns the predicate error which is provided to this function as an argument
Expand Down Expand Up @@ -185,8 +194,12 @@ func checkName(db *BlockDevice) (string, bool) {
return "", true
}

type FilterOptions struct {
AllowedBDTags map[string]bool
}

// Filter adds filters on which the blockdevice has to be filtered
func (bdl *BlockDeviceList) Filter(predicateKeys ...string) *BlockDeviceList {
func (bdl *BlockDeviceList) Filter(filterOps *FilterOptions, predicateKeys ...string) *BlockDeviceList {
// Initialize filtered block device list
filteredBlockDeviceList := &BlockDeviceList{
BlockDeviceList: &ndm.BlockDeviceList{},
Expand All @@ -199,6 +212,9 @@ func (bdl *BlockDeviceList) Filter(predicateKeys ...string) *BlockDeviceList {
}
filteredBlockDeviceList = bdl
for _, key := range predicateKeys {
if key == FilterNotAllowedBDTag {
bdFilterOptions.AllowedBDTags = filterOps.AllowedBDTags
}
filteredBlockDeviceList = filterOptionFuncMap[key](filteredBlockDeviceList)
}
return filteredBlockDeviceList
Expand Down Expand Up @@ -326,6 +342,26 @@ func filterNonRelesedDevices(originalList *BlockDeviceList) *BlockDeviceList {
return filteredList
}

func filterNotAllowedBDTag(originalList *BlockDeviceList) *BlockDeviceList {
filteredList := &BlockDeviceList{
BlockDeviceList: &ndm.BlockDeviceList{},
errs: nil,
}
for _, device := range originalList.Items {
value, ok := device.Labels[BlockDeviceTagLabelKey]
bdTag := strings.TrimSpace(value)
if ok {
if bdTag == "" || !bdFilterOptions.AllowedBDTags[bdTag] {
continue
}
filteredList.Items = append(filteredList.Items, device)
} else {
filteredList.Items = append(filteredList.Items, device)
}
}
return filteredList
}

// Hasitems checks whether the BlockDeviceList contains BlockDevices
func (bdl *BlockDeviceList) Hasitems() (string, bool) {
if bdl == nil || bdl.BlockDeviceList == nil || bdl.Items == nil {
Expand Down
Loading