Skip to content

Commit

Permalink
Add required port names to igroup
Browse files Browse the repository at this point in the history
  • Loading branch information
prajwalv-netapp authored Jan 7, 2025
1 parent 27f7cdc commit fcaeb45
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 42 deletions.
2 changes: 1 addition & 1 deletion frontend/csi/controller_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ func (p *Plugin) ControllerPublishVolume(
Localhost: false,
HostIQN: []string{nodeInfo.IQN},
HostNQN: nodeInfo.NQN,
HostWWPN: nodeInfo.WWPNs,
HostWWPNMap: nodeInfo.HostWWPNMap,
HostIP: nodeInfo.IPs,
HostName: nodeInfo.Name,
Unmanaged: volume.Config.ImportNotManaged,
Expand Down
20 changes: 10 additions & 10 deletions frontend/csi/node_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -696,8 +696,8 @@ func (p *Plugin) nodeGetInfo(ctx context.Context) *models.Node {
Logc(ctx).WithField("IP Addresses", ips).Info("Discovered IP addresses.")
}

var fcWWPNs []string
if fcWWPNs, err = fcp.GetFCPHostPortNames(ctx); err != nil {
var hostWWPNMap map[string][]string
if hostWWPNMap, err = fcp.GetFCPInitiatorTargetMap(ctx); err != nil {
Logc(ctx).WithError(err).Warn("Problem getting FCP host node port name association.")
}

Expand Down Expand Up @@ -749,14 +749,14 @@ func (p *Plugin) nodeGetInfo(ctx context.Context) *models.Node {

// Generate node object.
node := &models.Node{
Name: p.nodeName,
IQN: iscsiWWN,
NQN: nvmeNQN,
WWPNs: fcWWPNs,
IPs: ips,
NodePrep: nil,
HostInfo: p.hostInfo,
Deleted: false,
Name: p.nodeName,
IQN: iscsiWWN,
NQN: nvmeNQN,
HostWWPNMap: hostWWPNMap,
IPs: ips,
NodePrep: nil,
HostInfo: p.hostInfo,
Deleted: false,
// If the node is already known to exist Trident CSI Controllers persistence layer,
// that state will be used instead. Otherwise, node state defaults to clean.
PublicationState: models.NodeClean,
Expand Down
21 changes: 15 additions & 6 deletions storage_drivers/ontap/ontap_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -869,13 +869,22 @@ func PublishLUN(
}
} else if config.SANType == sa.FCP {
// Add wwpns to igroup
for _, hostWWPN := range publishInfo.HostWWPN {
portName := strings.TrimPrefix(hostWWPN, "0x")
wwpn := fcp.ConvertStrToWWNFormat(portName)

err = clientAPI.EnsureIgroupAdded(ctx, igroupName, wwpn)
if err != nil {
return fmt.Errorf("error adding WWPN %v to igroup %v: %v", portName, igroupName, err)
// Get the WWPNs and WWNNs from the host and propagate only the ones which are mapped to SVM
for initiatorPortName, targetPortNames := range publishInfo.HostWWPNMap {
// Format the WWNNs to match the SVM WWNNs
for _, targetPortName := range targetPortNames {
portNameFormatted := fcp.ConvertStrToWWNFormat(strings.TrimPrefix(targetPortName, "0x"))
// Add initiator port name to igroup, if the target port name is mapped to SVM
if nodeName == portNameFormatted {
portName := strings.TrimPrefix(initiatorPortName, "0x")
wwpn := fcp.ConvertStrToWWNFormat(portName)

err = clientAPI.EnsureIgroupAdded(ctx, igroupName, wwpn)
if err != nil {
return fmt.Errorf("error adding WWPN %v to igroup %v: %v", portName, igroupName, err)
}
}
}
}
}
Expand Down
105 changes: 100 additions & 5 deletions utils/fcp/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"context"
"os"
"path"
"slices"
"strings"

. "github.com/netapp/trident/logging"
Expand All @@ -15,16 +16,18 @@ import (
// top-level package.
// TODO (vivintw) remove this file once the refactoring is done.

func GetFCPHostPortNames(ctx context.Context) ([]string, error) {
var wwpns []string
// getFCPInitiatorPortName returns a map of initiator port names for each host.
// e.g. map[host11 : 0x50014380242c2b7d]
func getFCPInitiatorPortName(ctx context.Context) (map[string]string, error) {
initiatorPortNameMap := make(map[string]string)

// TODO (vhs) : Get the chroot path from the config and prefix it to the path
sysPath := "/sys/class/fc_host"

rportDirs, err := os.ReadDir(sysPath)
if err != nil {
Logc(ctx).WithField("error", err).Errorf("Could not read %s", sysPath)
return wwpns, err
return initiatorPortNameMap, err
}

for _, rportDir := range rportDirs {
Expand All @@ -39,10 +42,102 @@ func GetFCPHostPortNames(ctx context.Context) ([]string, error) {
continue
}

wwpns = append(wwpns, strings.TrimSpace(string(portName)))
initiatorPortNameMap[hostName] = strings.TrimSpace(string(portName))
}

return wwpns, nil
return initiatorPortNameMap, nil
}

// getFCPRPortsDirectories returns the directories under the given path that start with "rport".
// e.g. /sys/class/fc_host/host11/device/rport-11:0-1
func getFCPRPortsDirectories(ctx context.Context, path string) ([]string, error) {
var dirNames []string

rportDirs, err := os.ReadDir(path)
if err != nil {
Logc(ctx).WithField("error", err).Errorf("Could not read %s", path)
return dirNames, err
}

for _, rportDir := range rportDirs {
name := rportDir.Name()
if strings.HasPrefix(name, "rport") {
dirNames = append(dirNames, name)
}
}

return dirNames, nil
}

// getFCPTargetPortNames returns a map of target port names for each host.
// e.g. map[host11 : [0x50014380242c2b7f, 0x50014380242c2b7e]]
func getFCPTargetPortNames(ctx context.Context) (map[string][]string, error) {
targetPortNamesMap := make(map[string][]string)

basePath := "/sys/class/fc_host"

hosts, err := os.ReadDir(basePath)
if err != nil {
Logc(ctx).WithField("error", err).Errorf("Could not read %s", basePath)
return targetPortNamesMap, err
}

for _, hostDir := range hosts {
deviceRPortDirectoryPath := path.Join(basePath, hostDir.Name(), "device")
deviceRPortDirs, err := getFCPRPortsDirectories(ctx, deviceRPortDirectoryPath)
if err != nil {
Logc(ctx).WithField("error", err).Errorf("Could not read %s", deviceRPortDirectoryPath)
continue
}

for _, deviceRPortDir := range deviceRPortDirs {
fcRemoteRPortsPath := path.Join(deviceRPortDirectoryPath, deviceRPortDir, "fc_remote_ports", deviceRPortDir, "node_name")
nodeName, err := os.ReadFile(fcRemoteRPortsPath)
if err != nil {
Logc(ctx).WithField("error", err).Errorf("Could not read node name for %s", nodeName)
continue
}

// Skip the node if it is not a valid node name
if strings.TrimSpace(string(nodeName)) != "0x0" {
targetPortNamesMap[hostDir.Name()] = append(targetPortNamesMap[hostDir.Name()], strings.TrimSpace(string(nodeName)))
}
}
}

// Remove duplicate node names
for key, values := range targetPortNamesMap {
targetPortNamesMap[key] = slices.Compact(values)
}

return targetPortNamesMap, nil
}

// GetFCPInitiatorTargetMap returns a map of initiator port name to target port names.
// e.g. map[0x50014380242c2b7d : [0x50014380242c2b7e]]
func GetFCPInitiatorTargetMap(ctx context.Context) (map[string][]string, error) {
hostWWPNMap := make(map[string][]string)

initiatorPortNameMap, err := getFCPInitiatorPortName(ctx)
if err != nil {
return hostWWPNMap, err
}

targetPortNamesMap, err := getFCPTargetPortNames(ctx)
if err != nil {
return hostWWPNMap, err
}

// Create a map of initiator to targets
for initiator, iPortName := range initiatorPortNameMap {
for target, tPortName := range targetPortNamesMap {
if initiator == target {
hostWWPNMap[iPortName] = tPortName
}
}
}

return hostWWPNMap, nil
}

// ConvertStrToWWNFormat converts a WWnumber from string to the format xx:xx:xx:xx:xx:xx:xx:xx.
Expand Down
40 changes: 20 additions & 20 deletions utils/models/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,23 +106,23 @@ type DFInfo struct {
}

type VolumePublishInfo struct {
Localhost bool `json:"localhost,omitempty"`
HostIQN []string `json:"hostIQN,omitempty"`
HostNQN string `json:"hostNQN,omitempty"`
HostWWPN []string `json:"hostWWPN,omitempty"`
HostIP []string `json:"hostIP,omitempty"`
BackendUUID string `json:"backendUUID,omitempty"`
Nodes []*Node `json:"nodes,omitempty"`
HostName string `json:"hostName,omitempty"`
FilesystemType string `json:"fstype,omitempty"`
SharedTarget bool `json:"sharedTarget,omitempty"`
DevicePath string `json:"devicePath,omitempty"`
RawDevicePath string `json:"rawDevicePath,omitempty"` // NOTE: devicePath was renamed to this 23.01-23.04
Unmanaged bool `json:"unmanaged,omitempty"`
StagingMountpoint string `json:"stagingMountpoint,omitempty"` // NOTE: Added in 22.04 release
TridentUUID string `json:"tridentUUID,omitempty"` // NOTE: Added in 22.07 release
LUKSEncryption string `json:"LUKSEncryption,omitempty"`
SANType string `json:"SANType,omitempty"`
Localhost bool `json:"localhost,omitempty"`
HostIQN []string `json:"hostIQN,omitempty"`
HostNQN string `json:"hostNQN,omitempty"`
HostWWPNMap map[string][]string `json:"hostWWPNMap,omitempty"`
HostIP []string `json:"hostIP,omitempty"`
BackendUUID string `json:"backendUUID,omitempty"`
Nodes []*Node `json:"nodes,omitempty"`
HostName string `json:"hostName,omitempty"`
FilesystemType string `json:"fstype,omitempty"`
SharedTarget bool `json:"sharedTarget,omitempty"`
DevicePath string `json:"devicePath,omitempty"`
RawDevicePath string `json:"rawDevicePath,omitempty"` // NOTE: devicePath was renamed to this 23.01-23.04
Unmanaged bool `json:"unmanaged,omitempty"`
StagingMountpoint string `json:"stagingMountpoint,omitempty"` // NOTE: Added in 22.04 release
TridentUUID string `json:"tridentUUID,omitempty"` // NOTE: Added in 22.07 release
LUKSEncryption string `json:"LUKSEncryption,omitempty"`
SANType string `json:"SANType,omitempty"`
VolumeAccessInfo
}

Expand Down Expand Up @@ -188,7 +188,7 @@ type Node struct {
Name string `json:"name"`
IQN string `json:"iqn,omitempty"`
NQN string `json:"nqn,omitempty"`
WWPNs []string `json:"wwpns,omitempty"`
HostWWPNMap map[string][]string `json:"hostWWPNMap,omitempty"`
IPs []string `json:"ips,omitempty"`
TopologyLabels map[string]string `json:"topologyLabels,omitempty"`
NodePrep *NodePrep `json:"nodePrep,omitempty"`
Expand All @@ -204,7 +204,7 @@ type NodeExternal struct {
Name string `json:"name"`
IQN string `json:"iqn,omitempty"`
NQN string `json:"nqn,omitempty"`
WWPNs []string `json:"wwpns,omitempty"`
HostWWPNMap map[string][]string `json:"hostWWPNMap,omitempty"`
IPs []string `json:"ips,omitempty"`
TopologyLabels map[string]string `json:"topologyLabels,omitempty"`
NodePrep *NodePrep `json:"nodePrep,omitempty"`
Expand Down Expand Up @@ -237,7 +237,7 @@ func (n *Node) ConstructExternal() *NodeExternal {
Name: node.Name,
IQN: node.IQN,
NQN: node.NQN,
WWPNs: node.WWPNs,
HostWWPNMap: node.HostWWPNMap,
IPs: node.IPs,
TopologyLabels: node.TopologyLabels,
NodePrep: node.NodePrep,
Expand Down

0 comments on commit fcaeb45

Please sign in to comment.