Skip to content

Commit fcaeb45

Browse files
Add required port names to igroup
1 parent 27f7cdc commit fcaeb45

File tree

5 files changed

+146
-42
lines changed

5 files changed

+146
-42
lines changed

frontend/csi/controller_server.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ func (p *Plugin) ControllerPublishVolume(
360360
Localhost: false,
361361
HostIQN: []string{nodeInfo.IQN},
362362
HostNQN: nodeInfo.NQN,
363-
HostWWPN: nodeInfo.WWPNs,
363+
HostWWPNMap: nodeInfo.HostWWPNMap,
364364
HostIP: nodeInfo.IPs,
365365
HostName: nodeInfo.Name,
366366
Unmanaged: volume.Config.ImportNotManaged,

frontend/csi/node_server.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -696,8 +696,8 @@ func (p *Plugin) nodeGetInfo(ctx context.Context) *models.Node {
696696
Logc(ctx).WithField("IP Addresses", ips).Info("Discovered IP addresses.")
697697
}
698698

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

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

750750
// Generate node object.
751751
node := &models.Node{
752-
Name: p.nodeName,
753-
IQN: iscsiWWN,
754-
NQN: nvmeNQN,
755-
WWPNs: fcWWPNs,
756-
IPs: ips,
757-
NodePrep: nil,
758-
HostInfo: p.hostInfo,
759-
Deleted: false,
752+
Name: p.nodeName,
753+
IQN: iscsiWWN,
754+
NQN: nvmeNQN,
755+
HostWWPNMap: hostWWPNMap,
756+
IPs: ips,
757+
NodePrep: nil,
758+
HostInfo: p.hostInfo,
759+
Deleted: false,
760760
// If the node is already known to exist Trident CSI Controllers persistence layer,
761761
// that state will be used instead. Otherwise, node state defaults to clean.
762762
PublicationState: models.NodeClean,

storage_drivers/ontap/ontap_common.go

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -869,13 +869,22 @@ func PublishLUN(
869869
}
870870
} else if config.SANType == sa.FCP {
871871
// Add wwpns to igroup
872-
for _, hostWWPN := range publishInfo.HostWWPN {
873-
portName := strings.TrimPrefix(hostWWPN, "0x")
874-
wwpn := fcp.ConvertStrToWWNFormat(portName)
875872

876-
err = clientAPI.EnsureIgroupAdded(ctx, igroupName, wwpn)
877-
if err != nil {
878-
return fmt.Errorf("error adding WWPN %v to igroup %v: %v", portName, igroupName, err)
873+
// Get the WWPNs and WWNNs from the host and propagate only the ones which are mapped to SVM
874+
for initiatorPortName, targetPortNames := range publishInfo.HostWWPNMap {
875+
// Format the WWNNs to match the SVM WWNNs
876+
for _, targetPortName := range targetPortNames {
877+
portNameFormatted := fcp.ConvertStrToWWNFormat(strings.TrimPrefix(targetPortName, "0x"))
878+
// Add initiator port name to igroup, if the target port name is mapped to SVM
879+
if nodeName == portNameFormatted {
880+
portName := strings.TrimPrefix(initiatorPortName, "0x")
881+
wwpn := fcp.ConvertStrToWWNFormat(portName)
882+
883+
err = clientAPI.EnsureIgroupAdded(ctx, igroupName, wwpn)
884+
if err != nil {
885+
return fmt.Errorf("error adding WWPN %v to igroup %v: %v", portName, igroupName, err)
886+
}
887+
}
879888
}
880889
}
881890
}

utils/fcp/utils.go

Lines changed: 100 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"context"
77
"os"
88
"path"
9+
"slices"
910
"strings"
1011

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

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

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

2427
rportDirs, err := os.ReadDir(sysPath)
2528
if err != nil {
2629
Logc(ctx).WithField("error", err).Errorf("Could not read %s", sysPath)
27-
return wwpns, err
30+
return initiatorPortNameMap, err
2831
}
2932

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

42-
wwpns = append(wwpns, strings.TrimSpace(string(portName)))
45+
initiatorPortNameMap[hostName] = strings.TrimSpace(string(portName))
4346
}
4447

45-
return wwpns, nil
48+
return initiatorPortNameMap, nil
49+
}
50+
51+
// getFCPRPortsDirectories returns the directories under the given path that start with "rport".
52+
// e.g. /sys/class/fc_host/host11/device/rport-11:0-1
53+
func getFCPRPortsDirectories(ctx context.Context, path string) ([]string, error) {
54+
var dirNames []string
55+
56+
rportDirs, err := os.ReadDir(path)
57+
if err != nil {
58+
Logc(ctx).WithField("error", err).Errorf("Could not read %s", path)
59+
return dirNames, err
60+
}
61+
62+
for _, rportDir := range rportDirs {
63+
name := rportDir.Name()
64+
if strings.HasPrefix(name, "rport") {
65+
dirNames = append(dirNames, name)
66+
}
67+
}
68+
69+
return dirNames, nil
70+
}
71+
72+
// getFCPTargetPortNames returns a map of target port names for each host.
73+
// e.g. map[host11 : [0x50014380242c2b7f, 0x50014380242c2b7e]]
74+
func getFCPTargetPortNames(ctx context.Context) (map[string][]string, error) {
75+
targetPortNamesMap := make(map[string][]string)
76+
77+
basePath := "/sys/class/fc_host"
78+
79+
hosts, err := os.ReadDir(basePath)
80+
if err != nil {
81+
Logc(ctx).WithField("error", err).Errorf("Could not read %s", basePath)
82+
return targetPortNamesMap, err
83+
}
84+
85+
for _, hostDir := range hosts {
86+
deviceRPortDirectoryPath := path.Join(basePath, hostDir.Name(), "device")
87+
deviceRPortDirs, err := getFCPRPortsDirectories(ctx, deviceRPortDirectoryPath)
88+
if err != nil {
89+
Logc(ctx).WithField("error", err).Errorf("Could not read %s", deviceRPortDirectoryPath)
90+
continue
91+
}
92+
93+
for _, deviceRPortDir := range deviceRPortDirs {
94+
fcRemoteRPortsPath := path.Join(deviceRPortDirectoryPath, deviceRPortDir, "fc_remote_ports", deviceRPortDir, "node_name")
95+
nodeName, err := os.ReadFile(fcRemoteRPortsPath)
96+
if err != nil {
97+
Logc(ctx).WithField("error", err).Errorf("Could not read node name for %s", nodeName)
98+
continue
99+
}
100+
101+
// Skip the node if it is not a valid node name
102+
if strings.TrimSpace(string(nodeName)) != "0x0" {
103+
targetPortNamesMap[hostDir.Name()] = append(targetPortNamesMap[hostDir.Name()], strings.TrimSpace(string(nodeName)))
104+
}
105+
}
106+
}
107+
108+
// Remove duplicate node names
109+
for key, values := range targetPortNamesMap {
110+
targetPortNamesMap[key] = slices.Compact(values)
111+
}
112+
113+
return targetPortNamesMap, nil
114+
}
115+
116+
// GetFCPInitiatorTargetMap returns a map of initiator port name to target port names.
117+
// e.g. map[0x50014380242c2b7d : [0x50014380242c2b7e]]
118+
func GetFCPInitiatorTargetMap(ctx context.Context) (map[string][]string, error) {
119+
hostWWPNMap := make(map[string][]string)
120+
121+
initiatorPortNameMap, err := getFCPInitiatorPortName(ctx)
122+
if err != nil {
123+
return hostWWPNMap, err
124+
}
125+
126+
targetPortNamesMap, err := getFCPTargetPortNames(ctx)
127+
if err != nil {
128+
return hostWWPNMap, err
129+
}
130+
131+
// Create a map of initiator to targets
132+
for initiator, iPortName := range initiatorPortNameMap {
133+
for target, tPortName := range targetPortNamesMap {
134+
if initiator == target {
135+
hostWWPNMap[iPortName] = tPortName
136+
}
137+
}
138+
}
139+
140+
return hostWWPNMap, nil
46141
}
47142

48143
// ConvertStrToWWNFormat converts a WWnumber from string to the format xx:xx:xx:xx:xx:xx:xx:xx.

utils/models/types.go

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -106,23 +106,23 @@ type DFInfo struct {
106106
}
107107

108108
type VolumePublishInfo struct {
109-
Localhost bool `json:"localhost,omitempty"`
110-
HostIQN []string `json:"hostIQN,omitempty"`
111-
HostNQN string `json:"hostNQN,omitempty"`
112-
HostWWPN []string `json:"hostWWPN,omitempty"`
113-
HostIP []string `json:"hostIP,omitempty"`
114-
BackendUUID string `json:"backendUUID,omitempty"`
115-
Nodes []*Node `json:"nodes,omitempty"`
116-
HostName string `json:"hostName,omitempty"`
117-
FilesystemType string `json:"fstype,omitempty"`
118-
SharedTarget bool `json:"sharedTarget,omitempty"`
119-
DevicePath string `json:"devicePath,omitempty"`
120-
RawDevicePath string `json:"rawDevicePath,omitempty"` // NOTE: devicePath was renamed to this 23.01-23.04
121-
Unmanaged bool `json:"unmanaged,omitempty"`
122-
StagingMountpoint string `json:"stagingMountpoint,omitempty"` // NOTE: Added in 22.04 release
123-
TridentUUID string `json:"tridentUUID,omitempty"` // NOTE: Added in 22.07 release
124-
LUKSEncryption string `json:"LUKSEncryption,omitempty"`
125-
SANType string `json:"SANType,omitempty"`
109+
Localhost bool `json:"localhost,omitempty"`
110+
HostIQN []string `json:"hostIQN,omitempty"`
111+
HostNQN string `json:"hostNQN,omitempty"`
112+
HostWWPNMap map[string][]string `json:"hostWWPNMap,omitempty"`
113+
HostIP []string `json:"hostIP,omitempty"`
114+
BackendUUID string `json:"backendUUID,omitempty"`
115+
Nodes []*Node `json:"nodes,omitempty"`
116+
HostName string `json:"hostName,omitempty"`
117+
FilesystemType string `json:"fstype,omitempty"`
118+
SharedTarget bool `json:"sharedTarget,omitempty"`
119+
DevicePath string `json:"devicePath,omitempty"`
120+
RawDevicePath string `json:"rawDevicePath,omitempty"` // NOTE: devicePath was renamed to this 23.01-23.04
121+
Unmanaged bool `json:"unmanaged,omitempty"`
122+
StagingMountpoint string `json:"stagingMountpoint,omitempty"` // NOTE: Added in 22.04 release
123+
TridentUUID string `json:"tridentUUID,omitempty"` // NOTE: Added in 22.07 release
124+
LUKSEncryption string `json:"LUKSEncryption,omitempty"`
125+
SANType string `json:"SANType,omitempty"`
126126
VolumeAccessInfo
127127
}
128128

@@ -188,7 +188,7 @@ type Node struct {
188188
Name string `json:"name"`
189189
IQN string `json:"iqn,omitempty"`
190190
NQN string `json:"nqn,omitempty"`
191-
WWPNs []string `json:"wwpns,omitempty"`
191+
HostWWPNMap map[string][]string `json:"hostWWPNMap,omitempty"`
192192
IPs []string `json:"ips,omitempty"`
193193
TopologyLabels map[string]string `json:"topologyLabels,omitempty"`
194194
NodePrep *NodePrep `json:"nodePrep,omitempty"`
@@ -204,7 +204,7 @@ type NodeExternal struct {
204204
Name string `json:"name"`
205205
IQN string `json:"iqn,omitempty"`
206206
NQN string `json:"nqn,omitempty"`
207-
WWPNs []string `json:"wwpns,omitempty"`
207+
HostWWPNMap map[string][]string `json:"hostWWPNMap,omitempty"`
208208
IPs []string `json:"ips,omitempty"`
209209
TopologyLabels map[string]string `json:"topologyLabels,omitempty"`
210210
NodePrep *NodePrep `json:"nodePrep,omitempty"`
@@ -237,7 +237,7 @@ func (n *Node) ConstructExternal() *NodeExternal {
237237
Name: node.Name,
238238
IQN: node.IQN,
239239
NQN: node.NQN,
240-
WWPNs: node.WWPNs,
240+
HostWWPNMap: node.HostWWPNMap,
241241
IPs: node.IPs,
242242
TopologyLabels: node.TopologyLabels,
243243
NodePrep: node.NodePrep,

0 commit comments

Comments
 (0)