Skip to content

Commit

Permalink
Merge pull request #9 from dell/release-1.3.0.1
Browse files Browse the repository at this point in the history
Release 1.3.0.1
  • Loading branch information
bpjain2004 authored Nov 6, 2020
2 parents 3c6bb92 + ba2d8ed commit e91b21b
Show file tree
Hide file tree
Showing 9 changed files with 99 additions and 50 deletions.
15 changes: 1 addition & 14 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,6 @@ RUN microdnf install -y \
COPY --from=builder /go/src/csi-isilon /
ENTRYPOINT ["/csi-isilon"]

# Stage to check for critical and high CVE issues via Trivy (https://github.com/aquasecurity/trivy)
# will break image build if CRITICAL issues found
# will print out all HIGH issues found
FROM driver as cvescan
# run trivy and clean up all traces after
RUN microdnf install -y --enablerepo=ubi-8-baseos tar && \
microdnf clean all && \
curl https://raw.githubusercontent.com/aquasecurity/trivy/master/contrib/install.sh | sh && \
trivy fs -s CRITICAL --exit-code 1 / && \
trivy fs -s HIGH / && \
trivy image --reset && \
rm ./bin/trivy

# final stage
# simple stage to use the driver image as the resultant image
FROM driver as final
Expand All @@ -49,7 +36,7 @@ LABEL vendor="Dell Inc." \
name="csi-isilon" \
summary="CSI Driver for Dell EMC PowerScale" \
description="CSI Driver for provisioning persistent storage from Dell EMC PowerScale" \
version="1.3.0" \
version="1.3.0.1" \
license="Apache-2.0"

COPY ./licenses /licenses
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,26 @@ For clarity, Dell EMC does not provide support for any source code modifications

For any CSI driver issues, questions or feedback, join the [Dell EMC Container community](<https://www.dell.com/community/Containers/bd-p/Containers/>)

## Release Notes

Update below sample files of Dell CSI Operator corresponding to Isilon/PowerScale with latest Patch release : CSI Driver for Powerscale v1.3.0.1

**Note**: Replace image "dellemc/csi-isilon:v1.3.0.000R" with "dellemc/csi-isilon:v1.3.0.100R"

***Upstream Kubernetes***

samples/isilon_v130_k8s_117.yaml

samples/isilon_v130_k8s_118.yaml

samples/isilon_v130_k8s_119.yaml

***Openshift Environments***

samples/isilon_v130_ops_43.yaml

samples/isilon_v130_ops_44.yaml

## Overview

PowerScale CSI plugins implement an interface between CSI enabled Container Orchestrator(CO) and PowerScale Storage Array. It allows dynamically provisioning PowerScale volumes
Expand Down Expand Up @@ -416,3 +436,5 @@ On UCP based clusters, kubectl may not be installed by default, it is important
installation of the driver.

The worker nodes on UCP backed clusters may run any of the OSs which we support with upstream clusters.


19 changes: 19 additions & 0 deletions common/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,12 @@ var VolumeIDSeparator = "=_=_="
// VolumeIDPattern is the regex pattern that identifies the quota id set in the export's description field set by csi driver
var VolumeIDPattern = regexp.MustCompile(fmt.Sprintf("^(.+)%s(\\d+)%s(.+)$", VolumeIDSeparator, VolumeIDSeparator))

// NodeIDSeparator is the separator that separates node name and IP Address
var NodeIDSeparator = "=#=#="

// NodeIDPattern is the regex pattern that identifies the NodeID
var NodeIDPattern = regexp.MustCompile(fmt.Sprintf("^(.+)%s(.+)$", NodeIDSeparator))

// ExportConflictMessagePattern is the regex pattern that identifies the error message of export conflict
var ExportConflictMessagePattern = regexp.MustCompile(fmt.Sprintf("^Export rules (\\d+) and (\\d+) conflict on '(.+)'$"))

Expand Down Expand Up @@ -357,6 +363,19 @@ func ParseNormalizedVolumeID(volID string) (string, int, string, error) {
return matches[1], exportID, matches[3], nil
}

// Parses NodeID to node name and IP address using pattern '^(.+)=#=#=(.+)$'
func ParseNodeID(nodeID string) (string, string, error) {
matches := NodeIDPattern.FindStringSubmatch(nodeID)

if len(matches) < 3 {
return "", "", fmt.Errorf("node ID '%s' cannot match the expected '^(.+)=#=#=(.+)$' pattern", nodeID)
}

log.Debugf("Node ID '%s' parsed into node name '%s' and IP address '%s'", nodeID, matches[1], matches[2])

return matches[1], matches[2], nil
}

// GetPathForVolume gets the volume full path by the combination of isiPath and volumeName
func GetPathForVolume(isiPath, volName string) string {
if isiPath == "" {
Expand Down
4 changes: 2 additions & 2 deletions helm/csi-isilon/Chart.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: csi-isilon
version: 1.3.0
appVersion: 1.3.0
version: 1.3.0.1
appVersion: 1.3.0.1
description: |
PowerScale CSI (Container Storage Interface) driver Kubernetes
integration. This chart includes everything required to provision via CSI as
Expand Down
2 changes: 1 addition & 1 deletion helm/csi-isilon/driver-image.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# IT IS RECOMMENDED YOU DO NOT CHANGE THE IMAGES TO BE DOWNLOADED.
images:
# "images.driver" defines the container images used for the driver container.
driver: dellemc/csi-isilon:v1.3.0.000R
driver: dellemc/csi-isilon:v1.3.0.100R
62 changes: 33 additions & 29 deletions service/isiService.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ package service
import (
"context"
"fmt"
"net"

utils "github.com/dell/csi-isilon/common/utils"
isi "github.com/dell/goisilon"
Expand Down Expand Up @@ -341,53 +340,52 @@ func (svc *isiService) IsVolumeExistent(isiPath, volID, name string) bool {
return isExistent
}

func (svc *isiService) OtherClientsAlreadyAdded(exportID int, accessZone string, clientIP string) bool {
func (svc *isiService) OtherClientsAlreadyAdded(exportID int, accessZone string, nodeID string) bool {
export, _ := svc.GetExportByIDWithZone(exportID, accessZone)

if export == nil {
log.Debugf("failed to get export by id '%d' with access zone '%s', return true for otherClientsAlreadyAdded as a safer return value", exportID, accessZone)
return true
}

clientFieldsNotEmpty := len(*export.Clients) > 0 || len(*export.ReadOnlyClients) > 0 || len(*export.ReadWriteClients) > 0 || len(*export.RootClients) > 0
clientFQDN, clientIP, err := utils.ParseNodeID(nodeID)
if err != nil {
log.Debugf("failed to parse node ID '%s', return true for otherClientsAlreadyAdded as a safer return value", nodeID)
return true
}

isNodeInClientFields := utils.IsStringInSlices(clientIP, *export.Clients, *export.ReadOnlyClients, *export.ReadWriteClients, *export.RootClients)
clientFieldsNotEmpty := len(*export.Clients) > 0 || len(*export.ReadOnlyClients) > 0 || len(*export.ReadWriteClients) > 0 || len(*export.RootClients) > 0

fqdn, _ := utils.GetFQDNByIP(clientIP)
isNodeInClientFields := utils.IsStringInSlices(clientFQDN, *export.Clients, *export.ReadOnlyClients, *export.ReadWriteClients, *export.RootClients)

if fqdn != "" {
isNodeInClientFields = isNodeInClientFields || utils.IsStringInSlices(fqdn, *export.Clients, *export.ReadOnlyClients, *export.ReadWriteClients, *export.RootClients)
if clientIP != "" {
isNodeInClientFields = isNodeInClientFields || utils.IsStringInSlices(clientIP, *export.Clients, *export.ReadOnlyClients, *export.ReadWriteClients, *export.RootClients)
}

return clientFieldsNotEmpty && !isNodeInClientFields
}

func (svc *isiService) AddExportClientNetworkIdentifierByIDWithZone(exportID int, accessZone, clientIP string, addClientFunc func(exportID int, accessZone, clientIP string) error) error {
log.Debugf("AddExportClientNetworkIdentifierByID client ip '%s'", clientIP)
func (svc *isiService) AddExportClientNetworkIdentifierByIDWithZone(exportID int, accessZone, nodeID string, addClientFunc func(exportID int, accessZone, clientIP string) error) error {

var fqdn string
if net.ParseIP(clientIP) != nil {
fqdn, _ = utils.GetFQDNByIP(clientIP)
log.Debugf("ip '%s' is resolved to '%s'", clientIP, fqdn)
} else {
fqdn = clientIP
log.Debugf("fqdn is '%s'", fqdn)
}
// try adding by client FQDN first as it is preferred over IP for its stableness.
// OneFS API will return error if it cannot resolve the client FQDN ,
// in that case, fall back to adding by IP

if fqdn != "" {
clientFQDN, clientIP, err := utils.ParseNodeID(nodeID)
if err != nil {
return err
}

// try adding by FQDN first as FQDN is preferred over IP for its stableness. OneFS API will return error if it cannot resolve the FQDN,
// in that case, fall back to adding by IP
var err error
if err = addClientFunc(exportID, accessZone, fqdn); err == nil {
log.Debugf("AddExportClientNetworkIdentifierByID client FQDN '%s' client IP '%s'", clientFQDN, clientIP)

//adding by FQDN is successful, no need to trying adding by IP
return nil
}
if err = addClientFunc(exportID, accessZone, clientFQDN); err == nil {

log.Errorf("failed to add client fqdn '%s' to export id '%d' : '%v', try using client ip '%s'", fqdn, exportID, err, clientIP)
//adding by client FQDN is successful, no need to trying adding by IP
return nil
}

log.Infof("failed to add client FQDN '%s' to export id '%d' : '%v'", clientFQDN, exportID, err)

if err := addClientFunc(exportID, accessZone, clientIP); err != nil {
return fmt.Errorf("failed to add client ip '%s' to export id '%d' : '%v'", clientIP, exportID, err)
}
Expand Down Expand Up @@ -419,10 +417,16 @@ func (svc *isiService) AddExportReadOnlyClientByIDWithZone(exportID int, accessZ
return nil
}

func (svc *isiService) RemoveExportClientByIDWithZone(exportID int, accessZone, clientIP string) error {
func (svc *isiService) RemoveExportClientByIDWithZone(exportID int, accessZone, nodeID string) error {
// it could either be IP or FQDN that has been added to the export's client fields, should consider both during the removal
fqdn, _ := utils.GetFQDNByIP(clientIP)
clientsToRemove := []string{clientIP, fqdn}
clientFQDN, clientIP, err := utils.ParseNodeID(nodeID)
if err != nil {
return err
}

log.Debugf("RemoveExportClientByIDWithZone client FQDN '%s' client IP '%s'", clientFQDN, clientIP)

clientsToRemove := []string{clientIP, clientFQDN}

log.Debugf("RemoveExportClientByName client IP '%v'", clientsToRemove)

Expand Down
11 changes: 9 additions & 2 deletions service/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ package service
import (
"errors"
"fmt"

csi "github.com/container-storage-interface/spec/lib/go/csi"
"github.com/dell/csi-isilon/common/utils"
log "github.com/sirupsen/logrus"
Expand Down Expand Up @@ -182,11 +181,19 @@ func (s *service) NodeGetInfo(
req *csi.NodeGetInfoRequest) (
*csi.NodeGetInfoResponse, error) {

nodeID, err := s.GetCSINodeID(ctx)
// Fetch node pod FQDN
nodeID, err := utils.GetOwnFQDN()
if (err) != nil {
return nil, err
}

nodeIP, err := s.GetCSINodeIP(ctx)
if (err) != nil {
return nil, err
}

nodeID = nodeID + utils.NodeIDSeparator + nodeIP

return &csi.NodeGetInfoResponse{NodeId: nodeID}, nil
}

Expand Down
10 changes: 10 additions & 0 deletions service/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,16 @@ func (s *service) GetCSINodeID(ctx context.Context) (string, error) {
return "", errors.New("Cannot get node id")
}

// GetCSINodeIP gets the IP of the CSI node
func (s *service) GetCSINodeIP(ctx context.Context) (string, error) {
// if the node ip has already been initialized, return it
if s.nodeIP != "" {
return s.nodeIP, nil
}
// node id couldn't be read from env variable while initializing service, return with error
return "", errors.New("Cannot get node IP")
}

func (s *service) getVolByName(isiPath, volName string) (isi.Volume, error) {

// The `GetVolume` API returns a slice of volumes, but when only passing
Expand Down
4 changes: 2 additions & 2 deletions service/step_defs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ func (f *feature) getService() *service {
svc.opts = opts
svc.mode = "controller"
f.service = svc
f.service.nodeID = "k8s-rhel76-qual-1.1.1.1"
f.service.nodeID = "k8s-rhel76-qual-1-1-1-1"
f.service.nodeIP = "1.1.1.1"

utils.ConfigureLogger(opts.DebugEnabled)
Expand Down Expand Up @@ -1606,7 +1606,7 @@ func (f *feature) getServiceWithParams(user, mode string) *service {
svc.opts = opts
svc.mode = mode
f.service = svc
f.service.nodeID = "k8s-rhel76-qual-1.1.1.1"
f.service.nodeID = "k8s-rhel76-qual-1-1-1-1"
f.service.nodeIP = "1.1.1.1"
utils.ConfigureLogger(opts.DebugEnabled)
return svc
Expand Down

0 comments on commit e91b21b

Please sign in to comment.