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.
0 commit comments