Skip to content

Commit

Permalink
refactor(localpv): move the pv parsing to pv helper package (openebs-…
Browse files Browse the repository at this point in the history
…archive#1304)

This PR moves the logic to parse the PV attributes to
PV helper pkg.

Signed-off-by: kmova <[email protected]>
(cherry picked from commit 4a1a208)
  • Loading branch information
kmova committed Jun 19, 2019
1 parent 2cf4653 commit 8ec5e59
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 67 deletions.
59 changes: 0 additions & 59 deletions cmd/provisioner-localpv/app/helper_hostpath.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,10 @@ and modified to work with the configuration options used by OpenEBS
package app

import (
//"fmt"
"path/filepath"
//"strings"
"time"

"github.com/golang/glog"
//"github.com/pkg/errors"
errors "github.com/openebs/maya/pkg/errors/v1alpha1"

hostpath "github.com/openebs/maya/pkg/hostpath/v1alpha1"
Expand Down Expand Up @@ -71,60 +68,6 @@ func (pOpts *HelperPodOptions) validate() error {
return nil
}

// getPathAndNodeForPV inspects the PV spec to determine the hostpath
// and the node of OpenEBS Local PV. Both types of OpenEBS Local PV
// (storage type = hostpath and device) use:
// - LocalVolumeSource to specify the path and
// - NodeAffinity to specify the node.
// Note: This function also takes care of deleting OpenEBS Local PVs
// provisioned in 0.9, which were using HostPathVolumeSource to
// specify the path.
func (p *Provisioner) getPathAndNodeForPV(pv *corev1.PersistentVolume) (string, string, error) {
path := ""
local := pv.Spec.PersistentVolumeSource.Local
if local == nil {
//Handle the case of Local PV created in 0.9 using
//HostPathVolumeSource
hostPath := pv.Spec.PersistentVolumeSource.HostPath
if hostPath == nil {
return "", "", errors.Errorf("no HostPath set")
}
path = hostPath.Path
} else {
path = local.Path
}

nodeAffinity := pv.Spec.NodeAffinity
if nodeAffinity == nil {
return "", "", errors.Errorf("no NodeAffinity set")
}
required := nodeAffinity.Required
if required == nil {
return "", "", errors.Errorf("no NodeAffinity.Required set")
}

node := ""
for _, selectorTerm := range required.NodeSelectorTerms {
for _, expression := range selectorTerm.MatchExpressions {
if expression.Key == KeyNode &&
expression.Operator == corev1.NodeSelectorOpIn {
if len(expression.Values) != 1 {
return "", "", errors.Errorf("multiple values for the node affinity")
}
node = expression.Values[0]
break
}
}
if node != "" {
break
}
}
if node == "" {
return "", "", errors.Errorf("cannot find affinited node")
}
return path, node, nil
}

// createInitPod launches a helper(busybox) pod, to create the host path.
// The local pv expect the hostpath to be already present before mounting
// into pod. Validate that the local pv host path is not created under root.
Expand Down Expand Up @@ -197,7 +140,6 @@ func (p *Provisioner) createInitPod(pOpts *HelperPodOptions) error {
return errors.Errorf("create process timeout after %v seconds", CmdTimeoutCounts)
}

//glog.Infof("Volume %v has been initialized on %v:%v", pOpts.name, pOpts.nodeName, pOpts.path)
return nil
}

Expand Down Expand Up @@ -275,6 +217,5 @@ func (p *Provisioner) createCleanupPod(pOpts *HelperPodOptions) error {
return errors.Errorf("create process timeout after %v seconds", CmdTimeoutCounts)
}

glog.Infof("Volume %v has been cleaned on %v:%v", pOpts.name, pOpts.nodeName, pOpts.path)
return nil
}
17 changes: 11 additions & 6 deletions cmd/provisioner-localpv/app/provisioner_hostpath.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,8 @@ import (

pvController "github.com/kubernetes-sigs/sig-storage-lib-external-provisioner/controller"
mconfig "github.com/openebs/maya/pkg/apis/openebs.io/v1alpha1"
mPV "github.com/openebs/maya/pkg/kubernetes/persistentvolume/v1alpha1"
persistentvolume "github.com/openebs/maya/pkg/kubernetes/persistentvolume/v1alpha1"
"k8s.io/api/core/v1"
//metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// ProvisionHostPath is invoked by the Provisioner which expect HostPath PV
Expand Down Expand Up @@ -76,7 +75,7 @@ func (p *Provisioner) ProvisionHostPath(opts pvController.VolumeOptions, volumeC
//labels[string(v1alpha1.StorageClassKey)] = *className

//TODO Change the following to a builder pattern
pvObj, err := mPV.NewBuilder().
pvObj, err := persistentvolume.NewBuilder().
WithName(name).
WithLabels(labels).
WithReclaimPolicy(opts.PersistentVolumeReclaimPolicy).
Expand Down Expand Up @@ -105,9 +104,15 @@ func (p *Provisioner) DeleteHostPath(pv *v1.PersistentVolume) (err error) {
}()

//Determine the path and node of the Local PV.
path, node, err := p.getPathAndNodeForPV(pv)
if err != nil {
return err
pvObj := persistentvolume.NewForAPIObject(pv)
path := pvObj.GetPath()
if path == "" {
return errors.Errorf("no HostPath set")
}

node := pvObj.GetAffinitedNode()
if node == "" {
return errors.Errorf("cannot find affinited node")
}

//Initiate clean up only when reclaim policy is not retain.
Expand Down
2 changes: 1 addition & 1 deletion pkg/kubernetes/persistentvolume/v1alpha1/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ func (b *Builder) WithNodeAffinity(nodeName string) *Builder {
{
MatchExpressions: []corev1.NodeSelectorRequirement{
{
Key: "kubernetes.io/hostname",
Key: KeyNode,
Operator: corev1.NodeSelectorOpIn,
Values: []string{
nodeName,
Expand Down
2 changes: 1 addition & 1 deletion pkg/kubernetes/persistentvolume/v1alpha1/build_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ func TestBuildHostPath(t *testing.T) {
{
MatchExpressions: []corev1.NodeSelectorRequirement{
{
Key: "kubernetes.io/hostname",
Key: KeyNode,
Operator: corev1.NodeSelectorOpIn,
Values: []string{
"node1",
Expand Down
6 changes: 6 additions & 0 deletions pkg/kubernetes/persistentvolume/v1alpha1/kubernetes.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ import (
"k8s.io/client-go/kubernetes"
)

const (
//KeyNode represents the key values used for specifying the Node Affinity
// based on the hostname
KeyNode = "kubernetes.io/hostname"
)

// getClientsetFn is a typed function that
// abstracts fetching of clientset
type getClientsetFn func() (clientset *kubernetes.Clientset, err error)
Expand Down
47 changes: 47 additions & 0 deletions pkg/kubernetes/persistentvolume/v1alpha1/persistentvolume.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,53 @@ func (p *PV) IsNil() bool {
return p.object == nil
}

// GetPath returns path configured on VolumeSource
// The VolumeSource can be either Local or HostPath
func (p *PV) GetPath() string {
local := p.object.Spec.PersistentVolumeSource.Local
if local != nil {
return local.Path
}
//Handle the case of Local PV created in 0.9 using
//HostPath VolumeSource
hostPath := p.object.Spec.PersistentVolumeSource.HostPath
if hostPath != nil {
return hostPath.Path
}
return ""
}

// GetAffinitedNode returns nodeName configured using the NodeAffinity
// This method expects only a single node to be set.
func (p *PV) GetAffinitedNode() string {
nodeAffinity := p.object.Spec.NodeAffinity
if nodeAffinity == nil {
return ""
}
required := nodeAffinity.Required
if required == nil {
return ""
}

node := ""
for _, selectorTerm := range required.NodeSelectorTerms {
for _, expression := range selectorTerm.MatchExpressions {
if expression.Key == KeyNode &&
expression.Operator == corev1.NodeSelectorOpIn {
if len(expression.Values) != 1 {
return ""
}
node = expression.Values[0]
break
}
}
if node != "" {
break
}
}
return node
}

// IsNil is predicate to filter out nil PV
// instances
func IsNil() Predicate {
Expand Down

0 comments on commit 8ec5e59

Please sign in to comment.